public inbox for elfutils@sourceware.org
 help / color / mirror / Atom feed
* [PATCH 0/5] Add support for MIPS
@ 2023-04-11  8:12 Ying Huang
  2023-04-11  8:12 ` [PATCH 1/5] strip: Adapt src/strip -o -f on mips Ying Huang
                   ` (5 more replies)
  0 siblings, 6 replies; 30+ messages in thread
From: Ying Huang @ 2023-04-11  8:12 UTC (permalink / raw)
  To: elfutils-devel

[-- Attachment #1: Type: text/plain, Size: 182 bytes --]

This is a series of modifications about MIPS.
Support src/readelf, strip, unstrip, elflint, objdump related tools.
Pass all previous test cases that failed due to MIPS non-support.

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH 1/5] strip: Adapt src/strip -o -f on mips
  2023-04-11  8:12 [PATCH 0/5] Add support for MIPS Ying Huang
@ 2023-04-11  8:12 ` Ying Huang
  2023-05-09 15:15   ` Mark Wielaard
  2023-04-11  8:12 ` [PATCH 2/5] readelf: Adapt src/readelf -h/-S/-r/-w/-l/-d/-a " Ying Huang
                   ` (4 subsequent siblings)
  5 siblings, 1 reply; 30+ messages in thread
From: Ying Huang @ 2023-04-11  8:12 UTC (permalink / raw)
  To: elfutils-devel; +Cc: Ying Huang

[-- Attachment #1: Type: text/plain, Size: 22527 bytes --]

From: Ying Huang <ying.huang@oss.cipunited.com>

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.
---
 backends/Makefile.am    |  6 ++-
 backends/mips_init.c    | 49 +++++++++++++++++++++
 backends/mips_reloc.def | 93 +++++++++++++++++++++++++++++++++++++++
 backends/mips_symbol.c  | 62 ++++++++++++++++++++++++++
 libebl/eblopenbackend.c |  2 +
 libelf/elf.h            | 65 +++++++++++++++++++++++++++-
 libelf/elf_getdata.c    | 96 +++++++++++++++++++++++++++++++++++++++--
 libelf/elf_update.c     | 53 +++++++++++++++++++++++
 8 files changed, 419 insertions(+), 7 deletions(-)
 create mode 100644 backends/mips_init.c
 create mode 100644 backends/mips_reloc.def
 create mode 100644 backends/mips_symbol.c

diff --git a/backends/Makefile.am b/backends/Makefile.am
index f373e5fb..bda1b604 100644
--- a/backends/Makefile.am
+++ b/backends/Makefile.am
@@ -37,7 +37,7 @@ AM_CPPFLAGS += -I$(top_srcdir)/libebl -I$(top_srcdir)/libasm \
 noinst_LIBRARIES = libebl_backends.a libebl_backends_pic.a
 
 modules = i386 sh x86_64 ia64 alpha arm aarch64 sparc ppc ppc64 s390 \
-	  m68k bpf riscv csky loongarch arc
+	  m68k bpf riscv csky loongarch arc mips
 
 i386_SRCS = i386_init.c i386_symbol.c i386_corenote.c i386_cfi.c \
 	    i386_retval.c i386_regs.c i386_auxv.c \
@@ -100,12 +100,14 @@ loongarch_SRCS = loongarch_init.c loongarch_symbol.c
 
 arc_SRCS = arc_init.c arc_symbol.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) \
 			    $(aarch64_SRCS) $(sparc_SRCS) $(ppc_SRCS) \
 			    $(ppc64_SRCS) $(s390_SRCS) \
 			    $(m68k_SRCS) $(bpf_SRCS) $(riscv_SRCS) $(csky_SRCS) \
-			    $(loongarch_SRCS) $(arc_SRCS)
+			    $(loongarch_SRCS) $(arc_SRCS) $(mips_SRCS)
 
 libebl_backends_pic_a_SOURCES =
 am_libebl_backends_pic_a_OBJECTS = $(libebl_backends_a_SOURCES:.c=.os)
diff --git a/backends/mips_init.c b/backends/mips_init.c
new file mode 100644
index 00000000..f70d62e4
--- /dev/null
+++ b/backends/mips_init.c
@@ -0,0 +1,49 @@
+/* Initialization of MIPS specific backend library.
+   Copyright (C) 2023 CIP United Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#define BACKEND		mips_
+#define RELOC_PREFIX	R_MIPS_
+#include "libebl_CPU.h"
+
+/* This defines the common reloc hooks based on mips_reloc.def.  */
+#include "common-reloc.c"
+
+Ebl *
+mips_init (Elf *elf __attribute__ ((unused)),
+	   GElf_Half machine __attribute__ ((unused)),
+	   Ebl *eh)
+{
+  /* We handle it.  */
+  mips_init_reloc (eh);
+  HOOK (eh, reloc_simple_type);
+  return eh;
+}
diff --git a/backends/mips_reloc.def b/backends/mips_reloc.def
new file mode 100644
index 00000000..8cb66a54
--- /dev/null
+++ b/backends/mips_reloc.def
@@ -0,0 +1,93 @@
+/* List the relocation types for MIPS.  -*- C -*-
+   Copyright (C) 2023 CIP United Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+/*	    NAME,		REL|EXEC|DYN	*/
+
+
+RELOC_TYPE (NONE,		REL|EXEC|DYN)
+RELOC_TYPE (16,		        REL|EXEC|DYN)
+RELOC_TYPE (32,	                REL)
+RELOC_TYPE (REL32,	        REL|EXEC|DYN)
+RELOC_TYPE (26,		        REL|DYN)
+RELOC_TYPE (HI16,	        REL)
+RELOC_TYPE (LO16,		REL|EXEC|DYN)
+RELOC_TYPE (GPREL16,		REL|EXEC|DYN)
+RELOC_TYPE (LITERAL,		REL|EXEC|DYN)
+RELOC_TYPE (GOT16,		REL|EXEC|DYN)
+RELOC_TYPE (PC16,		REL)
+RELOC_TYPE (CALL16,		REL)
+RELOC_TYPE (GPREL32,		REL)
+RELOC_TYPE (SHIFT5,		REL)
+RELOC_TYPE (SHIFT6,		REL)
+RELOC_TYPE (64,		        REL)
+RELOC_TYPE (GOT_DISP,		REL)
+RELOC_TYPE (GOT_PAGE,		REL)
+RELOC_TYPE (GOT_OFST,		REL)
+RELOC_TYPE (GOT_HI16,		REL)
+RELOC_TYPE (GOT_LO16,		REL)
+RELOC_TYPE (SUB,		REL)
+RELOC_TYPE (INSERT_A,		REL)
+RELOC_TYPE (INSERT_B,		REL)
+RELOC_TYPE (DELETE,		REL)
+RELOC_TYPE (HIGHER,		REL)
+RELOC_TYPE (HIGHEST,		REL)
+RELOC_TYPE (CALL_HI16,		REL)
+RELOC_TYPE (CALL_LO16,		REL)
+RELOC_TYPE (SCN_DISP,		REL)
+RELOC_TYPE (REL16,		REL)
+RELOC_TYPE (ADD_IMMEDIATE,	REL)
+RELOC_TYPE (PJUMP,		REL)
+RELOC_TYPE (RELGOT,		REL)
+RELOC_TYPE (JALR,		REL)
+RELOC_TYPE (TLS_DTPMOD32,	DYN)
+RELOC_TYPE (TLS_DTPREL32,	REL)
+RELOC_TYPE (TLS_DTPMOD64,	DYN)
+RELOC_TYPE (TLS_DTPREL64,	REL)
+RELOC_TYPE (TLS_GD,		REL)
+RELOC_TYPE (TLS_LDM,		REL)
+RELOC_TYPE (TLS_DTPREL_HI16,	REL)
+RELOC_TYPE (TLS_DTPREL_LO16,	REL)
+RELOC_TYPE (TLS_GOTTPREL,	REL)
+RELOC_TYPE (TLS_TPREL32,	REL)
+RELOC_TYPE (TLS_TPREL64,	REL)
+RELOC_TYPE (TLS_TPREL_HI16,	REL)
+RELOC_TYPE (TLS_TPREL_LO16,	REL)
+RELOC_TYPE (GLOB_DAT,		REL)
+RELOC_TYPE (PC21_S2,		REL)
+RELOC_TYPE (PC26_S2,		REL)
+RELOC_TYPE (PC18_S3,		REL)
+RELOC_TYPE (PC19_S2,		REL)
+RELOC_TYPE (PCHI16,		REL)
+RELOC_TYPE (PCLO16,		REL)
+RELOC_TYPE (COPY,		REL)
+RELOC_TYPE (JUMP_SLOT,		REL)
+RELOC_TYPE (PC32,		REL)
+RELOC_TYPE (EH,			REL)
+RELOC_TYPE (GNU_REL16_S2,	REL)
+RELOC_TYPE (GNU_VTINHERIT,	REL)
+RELOC_TYPE (GNU_VTENTRY,	REL)
diff --git a/backends/mips_symbol.c b/backends/mips_symbol.c
new file mode 100644
index 00000000..4f1bd3e6
--- /dev/null
+++ b/backends/mips_symbol.c
@@ -0,0 +1,62 @@
+/* MIPS specific symbolic name handling.
+   Copyright (C) 2023 CIP United Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <system.h>
+
+#include <elf.h>
+#include <stddef.h>
+#include <string.h>
+#include <stdio.h>
+#define BACKEND		mips_
+#include "libebl_CPU.h"
+#include "libelfP.h"
+/* Check for the simple reloc types.  */
+Elf_Type
+mips_reloc_simple_type (Ebl *ebl, int type,
+			   int *addsub __attribute__ ((unused)))
+{
+  int typeNew = type;
+  if(ebl->elf->class == ELFCLASS64)
+    typeNew = ELF64_MIPS_R_TYPE(type);
+  switch (typeNew)
+    {
+    case R_MIPS_64:
+      return ELF_T_XWORD;
+    case R_MIPS_32:
+      return ELF_T_WORD;
+    case R_MIPS_16:
+      return ELF_T_HALF;
+
+    default:
+      return ELF_T_NUM;
+    }
+}
diff --git a/libebl/eblopenbackend.c b/libebl/eblopenbackend.c
index 084a1544..a5f7467a 100644
--- a/libebl/eblopenbackend.c
+++ b/libebl/eblopenbackend.c
@@ -57,6 +57,7 @@ Ebl *riscv_init (Elf *, GElf_Half, Ebl *);
 Ebl *csky_init (Elf *, GElf_Half, Ebl *);
 Ebl *loongarch_init (Elf *, GElf_Half, Ebl *);
 Ebl *arc_init (Elf *, GElf_Half, Ebl *);
+Ebl *mips_init (Elf *, GElf_Half, Ebl *);
 
 /* This table should contain the complete list of architectures as far
    as the ELF specification is concerned.  */
@@ -154,6 +155,7 @@ static const struct
   { csky_init, "elf_csky", "csky", 4, EM_CSKY, ELFCLASS32, ELFDATA2LSB },
   { loongarch_init, "elf_loongarch", "loongarch", 9, EM_LOONGARCH, ELFCLASS64, ELFDATA2LSB },
   { arc_init, "elf_arc", "arc", 3, EM_ARCV2, ELFCLASS32, ELFDATA2LSB },
+  { mips_init, "elf_mips", "mips", 4, EM_MIPS, 0, 0 },
 };
 #define nmachines (sizeof (machines) / sizeof (machines[0]))
 
diff --git a/libelf/elf.h b/libelf/elf.h
index 4bc0e429..aa903837 100644
--- a/libelf/elf.h
+++ b/libelf/elf.h
@@ -678,6 +678,9 @@ typedef Elf64_Xword	Elf64_Relr;
 
 #define ELF64_R_SYM(i)			((i) >> 32)
 #define ELF64_R_TYPE(i)			((i) & 0xffffffff)
+#define ELF64_MIPS_R_TYPE(i)		((i) & 0xff)
+#define ELF64_MIPS_R_TYPE2(i)           (((i) >> 8) & 0xff)
+#define ELF64_MIPS_R_TYPE3(i)           (((i) >> 16) & 0xff)
 #define ELF64_R_INFO(sym,type)		((((Elf64_Xword) (sym)) << 32) + (type))
 
 /* Program segment header.  */
@@ -1927,11 +1930,69 @@ typedef struct
 #define R_MIPS_TLS_TPREL_HI16	49	/* TP-relative offset, high 16 bits */
 #define R_MIPS_TLS_TPREL_LO16	50	/* TP-relative offset, low 16 bits */
 #define R_MIPS_GLOB_DAT		51
+#define R_MIPS_PC21_S2          60
+/* copy binutils-2.34/elfcpp/mips.h +102 */
+#define R_MIPS_PC26_S2          61
+#define R_MIPS_PC18_S3          62
+#define R_MIPS_PC19_S2          63
+#define R_MIPS_PCHI16           64
+#define R_MIPS_PCLO16           65
+#define R_MIPS16_26             100
+#define R_MIPS16_GPREL          101
+#define R_MIPS16_GOT16          102
+#define R_MIPS16_CALL16         103
+#define R_MIPS16_HI16           104
+#define R_MIPS16_LO16           105
+#define R_MIPS16_TLS_GD         106
+#define R_MIPS16_TLS_LDM        107
+#define R_MIPS16_TLS_DTPREL_HI16 108
+#define R_MIPS16_TLS_DTPREL_LO16 109
+#define R_MIPS16_TLS_GOTTPREL   110
+#define R_MIPS16_TLS_TPREL_HI16 111
+#define R_MIPS16_TLS_TPREL_LO16 112
+#define R_MIPS16_PC16_S1        113
 #define R_MIPS_COPY		126
 #define R_MIPS_JUMP_SLOT        127
+#define R_MIPS_RELATIVE         128
+#define R_MICROMIPS_26_S1       133
+#define R_MICROMIPS_HI16        134
+#define R_MICROMIPS_LO16        135
+#define R_MICROMIPS_GPREL16     136
+#define R_MICROMIPS_LITERAL     137
+#define R_MICROMIPS_GOT16       138
+#define R_MICROMIPS_PC7_S1      139
+#define R_MICROMIPS_PC10_S1     140
+#define R_MICROMIPS_PC16_S1     141
+#define R_MICROMIPS_CALL16      142
+#define R_MICROMIPS_GOT_DISP    145
+#define R_MICROMIPS_GOT_PAGE    146
+#define R_MICROMIPS_GOT_OFST    147
+#define R_MICROMIPS_GOT_HI16    148
+#define R_MICROMIPS_GOT_LO16    149
+#define R_MICROMIPS_SUB         150
+#define R_MICROMIPS_HIGHER      151
+#define R_MICROMIPS_HIGHEST     152
+#define R_MICROMIPS_CALL_HI16   153
+#define R_MICROMIPS_CALL_LO16   154
+#define R_MICROMIPS_SCN_DISP    155
+#define R_MICROMIPS_JALR        156
+#define R_MICROMIPS_HI0_LO16    157
+#define R_MICROMIPS_TLS_GD      162
+#define R_MICROMIPS_TLS_LDM     163
+#define R_MICROMIPS_TLS_DTPREL_HI16  164
+#define R_MICROMIPS_TLS_DTPREL_LO16  165
+#define R_MICROMIPS_TLS_GOTTPREL     166
+#define R_MICROMIPS_TLS_TPREL_HI16   169
+#define R_MICROMIPS_TLS_TPREL_LO16   170
+#define R_MICROMIPS_GPREL7_S2   172
+#define R_MICROMIPS_PC23_S2     173
+#define R_MIPS_PC32             248
+#define R_MIPS_EH               249
+#define R_MIPS_GNU_REL16_S2     250
+#define R_MIPS_GNU_VTINHERIT    253
+#define R_MIPS_GNU_VTENTRY      254
 /* Keep this the last entry.  */
-#define R_MIPS_NUM		128
-
+#define R_MIPS_NUM		255
 /* Legal values for p_type field of Elf32_Phdr.  */
 
 #define PT_MIPS_REGINFO	  0x70000000	/* Register usage information. */
diff --git a/libelf/elf_getdata.c b/libelf/elf_getdata.c
index 5ebd270f..80f91124 100644
--- a/libelf/elf_getdata.c
+++ b/libelf/elf_getdata.c
@@ -139,13 +139,38 @@ convert_data (Elf_Scn *scn, int eclass,
 	      int data, size_t size, Elf_Type type)
 {
   const size_t align = __libelf_type_align (eclass, type);
+  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);
 
   /* Do we need to convert the data and/or adjust for alignment?  */
   if (data == MY_ELFDATA || type == ELF_T_BYTE)
     {
       if (((((size_t) (char *) scn->rawdata_base)) & (align - 1)) == 0)
-	/* No need to copy, we can use the raw data.  */
-	scn->data_base = scn->rawdata_base;
+        {
+	  /* 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. */
+	  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)
+	    {
+	      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
+	    /* No need to copy, we can use the raw data.  */
+	    scn->data_base = scn->rawdata_base;
+        }
       else
 	{
 	  scn->data_base = malloc (size);
@@ -174,7 +199,28 @@ convert_data (Elf_Scn *scn, int eclass,
 	 function to directly access the data elements.  */
       char *rawdata_source;
       if (((((size_t) (char *) scn->rawdata_base)) & (align - 1)) == 0)
-	rawdata_source = scn->rawdata_base;
+        {
+	  /* 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. */
+	  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)
+	    {
+	      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);
+	    }
+	  else
+	    rawdata_source = scn->rawdata_base;
+	}
       else
 	{
 	  rawdata_source = malloc (size);
@@ -205,6 +251,50 @@ convert_data (Elf_Scn *scn, int eclass,
   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. */
+  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)
+    {
+      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;
+             }
+         }
+     }
 }
 
 
diff --git a/libelf/elf_update.c b/libelf/elf_update.c
index 56af3a1c..11027c38 100644
--- 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:
-- 
2.30.2

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH 2/5] readelf: Adapt src/readelf -h/-S/-r/-w/-l/-d/-a on mips
  2023-04-11  8:12 [PATCH 0/5] Add support for MIPS Ying Huang
  2023-04-11  8:12 ` [PATCH 1/5] strip: Adapt src/strip -o -f on mips Ying Huang
@ 2023-04-11  8:12 ` Ying Huang
  2023-05-11 14:31   ` Mark Wielaard
  2023-04-11  8:12 ` [PATCH 3/5] elflint: Fix invalid type of relocation info and other issues " Ying Huang
                   ` (3 subsequent siblings)
  5 siblings, 1 reply; 30+ messages in thread
From: Ying Huang @ 2023-04-11  8:12 UTC (permalink / raw)
  To: elfutils-devel; +Cc: Ying Huang

[-- Attachment #1: Type: text/plain, Size: 39312 bytes --]

From: Ying Huang <ying.huang@oss.cipunited.com>

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

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

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH 3/5] elflint: Fix invalid type of relocation info and other issues on mips
  2023-04-11  8:12 [PATCH 0/5] Add support for MIPS Ying Huang
  2023-04-11  8:12 ` [PATCH 1/5] strip: Adapt src/strip -o -f on mips Ying Huang
  2023-04-11  8:12 ` [PATCH 2/5] readelf: Adapt src/readelf -h/-S/-r/-w/-l/-d/-a " Ying Huang
@ 2023-04-11  8:12 ` Ying Huang
  2023-05-11 15:59   ` Mark Wielaard
  2023-04-11  8:12 ` [PATCH 4/5] stack: Fix stack unwind failure " Ying Huang
                   ` (2 subsequent siblings)
  5 siblings, 1 reply; 30+ messages in thread
From: Ying Huang @ 2023-04-11  8:12 UTC (permalink / raw)
  To: elfutils-devel; +Cc: Ying Huang

[-- Attachment #1: Type: text/plain, Size: 4656 bytes --]

From: Ying Huang <ying.huang@oss.cipunited.com>

add some check related functions
---
 backends/mips_init.c      |  3 +++
 backends/mips_symbol.c    | 33 +++++++++++++++++++++++++++++++++
 libebl/eblrelocvaliduse.c |  8 ++++++--
 src/elflint.c             | 23 ++++++++++++++++++++---
 4 files changed, 62 insertions(+), 5 deletions(-)

diff --git a/backends/mips_init.c b/backends/mips_init.c
index 5bba822b..4c2f21b9 100644
--- a/backends/mips_init.c
+++ b/backends/mips_init.c
@@ -51,6 +51,9 @@ mips_init (Elf *elf __attribute__ ((unused)),
   HOOK (eh, segment_type_name);
   HOOK (eh, dynamic_tag_check);
   HOOK (eh, dynamic_tag_name);
+  HOOK (eh, machine_section_flag_check);
   HOOK (eh, check_object_attribute);
+  HOOK (eh, check_special_symbol);
+  HOOK (eh, check_reloc_target_type);
   return eh;
 }
diff --git a/backends/mips_symbol.c b/backends/mips_symbol.c
index e760d58d..8787fcee 100644
--- a/backends/mips_symbol.c
+++ b/backends/mips_symbol.c
@@ -158,6 +158,39 @@ 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)) == 0);
+}
+
 /* Check whether machine flags are valid.  */
 bool
 mips_machine_flag_check (GElf_Word flags)
diff --git a/libebl/eblrelocvaliduse.c b/libebl/eblrelocvaliduse.c
index f0bed345..44b8d300 100644
--- a/libebl/eblrelocvaliduse.c
+++ b/libebl/eblrelocvaliduse.c
@@ -32,10 +32,14 @@
 #endif
 
 #include <libeblP.h>
-
+#include <libelfP.h>
 
 bool
 ebl_reloc_valid_use (Ebl *ebl, int reloc)
 {
-  return ebl != NULL ? ebl->reloc_valid_use (ebl->elf, reloc) : false;
+  int relocNew = reloc;
+  GElf_Ehdr ehdr;
+  if(ebl->elf->class == ELFCLASS64 && gelf_getehdr(ebl->elf, &ehdr) != NULL && ehdr.e_machine == EM_MIPS)
+    relocNew = ELF64_MIPS_R_TYPE(reloc);
+  return ebl != NULL ? ebl->reloc_valid_use (ebl->elf, relocNew) : false;
 }
diff --git a/src/elflint.c b/src/elflint.c
index dd42dcb4..04f1ee92 100644
--- a/src/elflint.c
+++ b/src/elflint.c
@@ -935,7 +935,10 @@ section [%2d] '%s': symbol %zu (%s): non-local symbol outside range described in
 	}
 
       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_LINK") != 0
+	  && strcmp (name, "_DYNAMIC_LINKING") != 0)
 	ERROR (_("\
 section [%2d] '%s': symbol %zu (%s): non-local section symbol\n"),
 	       idx, section_name (ebl, idx), cnt, name);
@@ -3789,6 +3792,12 @@ cannot get section header for section [%2zu] '%s': %s\n"),
 		    && 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
@@ -3953,8 +3962,16 @@ section [%2zu] '%s': size not multiple of entry size\n"),
 	      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 (ehdr->e_machine == EM_MIPS)
+	        {
+	          if(sh_flags == SHF_MIPS_NOSTRIP || sh_flags == SHF_MIPS_LOCAL
+		   || sh_flags == SHF_MIPS_NAMES || sh_flags == SHF_MIPS_NODUPE)
+	            sh_flags &= ~shdr->sh_flags;
+	        }
+	    }
 	  if (sh_flags != 0)
 	    ERROR (_("section [%2zu] '%s' contains unknown flag(s)"
 			    " %#" PRIx64 "\n"),
-- 
2.30.2

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH 4/5] stack: Fix stack unwind failure on mips
  2023-04-11  8:12 [PATCH 0/5] Add support for MIPS Ying Huang
                   ` (2 preceding siblings ...)
  2023-04-11  8:12 ` [PATCH 3/5] elflint: Fix invalid type of relocation info and other issues " Ying Huang
@ 2023-04-11  8:12 ` Ying Huang
  2023-05-11 16:07   ` Mark Wielaard
  2023-04-11  8:12 ` [PATCH 5/5] backends: Fix run-native-test.sh and run-funcretval++11.sh run fail " Ying Huang
  2023-05-04  2:24 ` [PATCH 0/5] Add support for MIPS 黄莺
  5 siblings, 1 reply; 30+ messages in thread
From: Ying Huang @ 2023-04-11  8:12 UTC (permalink / raw)
  To: elfutils-devel; +Cc: Ying Huang

[-- Attachment #1: Type: text/plain, Size: 9471 bytes --]

From: Ying Huang <ying.huang@oss.cipunited.com>

add abi_cfi, set_initial_registers_tid, unwind on mips.
"./src/stack -p PID" can show stack information
---
 backends/Makefile.am    |  3 +-
 backends/mips_cfi.c     | 68 +++++++++++++++++++++++++++++++++
 backends/mips_init.c    |  4 ++
 backends/mips_initreg.c | 70 ++++++++++++++++++++++++++++++++++
 backends/mips_unwind.c  | 84 +++++++++++++++++++++++++++++++++++++++++
 5 files changed, 228 insertions(+), 1 deletion(-)
 create mode 100644 backends/mips_cfi.c
 create mode 100644 backends/mips_initreg.c
 create mode 100644 backends/mips_unwind.c

diff --git a/backends/Makefile.am b/backends/Makefile.am
index 428a1a03..ddc31c9d 100644
--- a/backends/Makefile.am
+++ b/backends/Makefile.am
@@ -100,7 +100,8 @@ loongarch_SRCS = loongarch_init.c loongarch_symbol.c
 
 arc_SRCS = arc_init.c arc_symbol.c
 
-mips_SRCS = mips_init.c mips_symbol.c mips_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) \
diff --git a/backends/mips_cfi.c b/backends/mips_cfi.c
new file mode 100644
index 00000000..77132cc1
--- /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) 2023 CIP United Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <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 = -4;
+
+  abi_info->return_address_register = 31; /* %ra */
+
+  return 0;
+}
diff --git a/backends/mips_init.c b/backends/mips_init.c
index 4c2f21b9..3caa9fee 100644
--- a/backends/mips_init.c
+++ b/backends/mips_init.c
@@ -55,5 +55,9 @@ mips_init (Elf *elf __attribute__ ((unused)),
   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 = 32;
   return eh;
 }
diff --git a/backends/mips_initreg.c b/backends/mips_initreg.c
new file mode 100644
index 00000000..31b8de13
--- /dev/null
+++ b/backends/mips_initreg.c
@@ -0,0 +1,70 @@
+/* Fetch live process registers from TID.
+   Copyright (C) 2023 CIP United Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+#if (defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__)) && defined(__linux__)
+# include <sys/user.h>
+# include <sys/ptrace.h>
+#endif
+
+#define BACKEND mips_
+#include "libebl_CPU.h"
+#include <stdio.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 {
+    uint64_t regs[32];
+    uint64_t lo;
+    uint64_t hi;
+    uint64_t pc;
+    uint64_t badvaddr;
+    uint64_t cause;
+    uint64_t status;
+};
+
+  struct pt_regs gregs;
+  if (ptrace (PTRACE_GETREGS, tid, 0, &gregs) != 0)
+    return false;
+  if (! setfunc (-1, 1, (Dwarf_Word *) &gregs.pc, arg))
+    return false;
+  return setfunc (0, 32, (Dwarf_Word *) &gregs.regs[0], arg);
+#endif /* __mips__ */
+}
diff --git a/backends/mips_unwind.c b/backends/mips_unwind.c
new file mode 100644
index 00000000..d09db3a9
--- /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) 2023 CIP United Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#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;
+}
-- 
2.30.2

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH 5/5] backends: Fix run-native-test.sh and run-funcretval++11.sh run fail on mips
  2023-04-11  8:12 [PATCH 0/5] Add support for MIPS Ying Huang
                   ` (3 preceding siblings ...)
  2023-04-11  8:12 ` [PATCH 4/5] stack: Fix stack unwind failure " Ying Huang
@ 2023-04-11  8:12 ` Ying Huang
  2023-05-11 16:38   ` Mark Wielaard
  2023-05-04  2:24 ` [PATCH 0/5] Add support for MIPS 黄莺
  5 siblings, 1 reply; 30+ messages in thread
From: Ying Huang @ 2023-04-11  8:12 UTC (permalink / raw)
  To: elfutils-devel; +Cc: Ying Huang

[-- Attachment #1: Type: text/plain, Size: 12245 bytes --]

From: Ying Huang <ying.huang@oss.cipunited.com>

add register_info, return_value_location function on mips
---
 backends/Makefile.am   |   2 +-
 backends/mips_init.c   |   2 +
 backends/mips_regs.c   | 109 +++++++++++++++++
 backends/mips_retval.c | 261 +++++++++++++++++++++++++++++++++++++++++
 4 files changed, 373 insertions(+), 1 deletion(-)
 create mode 100644 backends/mips_regs.c
 create mode 100644 backends/mips_retval.c

diff --git a/backends/Makefile.am b/backends/Makefile.am
index ddc31c9d..5453f787 100644
--- a/backends/Makefile.am
+++ b/backends/Makefile.am
@@ -101,7 +101,7 @@ loongarch_SRCS = loongarch_init.c loongarch_symbol.c
 arc_SRCS = arc_init.c arc_symbol.c
 
 mips_SRCS = mips_init.c mips_symbol.c mips_attrs.c mips_initreg.c \
-	    mips_cfi.c mips_unwind.c
+	    mips_cfi.c mips_unwind.c mips_regs.c mips_retval.c
 
 libebl_backends_a_SOURCES = $(i386_SRCS) $(sh_SRCS) $(x86_64_SRCS) \
 			    $(ia64_SRCS) $(alpha_SRCS) $(arm_SRCS) \
diff --git a/backends/mips_init.c b/backends/mips_init.c
index 3caa9fee..7ca93314 100644
--- a/backends/mips_init.c
+++ b/backends/mips_init.c
@@ -58,6 +58,8 @@ mips_init (Elf *elf __attribute__ ((unused)),
   HOOK (eh, set_initial_registers_tid);
   HOOK (eh, abi_cfi);
   HOOK (eh, unwind);
+  HOOK (eh, register_info);
+  HOOK (eh, return_value_location);
   eh->frame_nregs = 32;
   return eh;
 }
diff --git a/backends/mips_regs.c b/backends/mips_regs.c
new file mode 100644
index 00000000..733caeee
--- /dev/null
+++ b/backends/mips_regs.c
@@ -0,0 +1,109 @@
+/* Register names and numbers for mips DWARF.
+   Copyright (C) 2006 Red Hat, Inc.
+   Copyright (C) 2023 CIP United Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <dwarf.h>
+#include <string.h>
+
+#define BACKEND mips_
+#include "libebl_CPU.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 66;
+
+  if (regno < 0 || regno > 65 || namelen < 4)
+    return -1;
+
+  *prefix = "$";
+  
+  if (regno < 32)
+    {
+      *setname = "integer";
+      *type = DW_ATE_signed;
+      *bits = 32;
+      if (regno < 32 + 10)
+      {
+        name[0] = regno + '0';
+	namelen = 1;
+      }
+      else
+      {
+        name[0] = (regno / 10) + '0';
+	name[1] = (regno % 10) + '0';
+	namelen = 2;
+      }
+    }
+  else if (regno < 64)
+    {
+      *setname = "FPU";
+      *type = DW_ATE_float;
+      *bits = 32;
+      name[0] = 'f';
+      if (regno < 32 + 10)
+      {
+        name[1] = (regno - 32) + '0';
+	namelen = 2;
+      }
+      else
+      {
+        name[1] = (regno - 32) / 10 + '0';
+	name[2] = (regno - 32) % 10 + '0';
+	namelen = 3;
+      }
+    }
+  else if (regno == 64)
+    {
+      *type = DW_ATE_signed;
+      *bits = 32;
+      name[0] = 'h';
+      name[1] = 'i';
+      namelen = 2;
+    }
+  else
+    {
+      *type = DW_ATE_signed;
+      *bits = 32;
+      name[0] = 'l';
+      name[1] = 'o';
+      namelen = 2;
+    }
+
+  name[namelen++] = '\0';
+  return namelen;
+}
diff --git a/backends/mips_retval.c b/backends/mips_retval.c
new file mode 100644
index 00000000..fd9aaefa
--- /dev/null
+++ b/backends/mips_retval.c
@@ -0,0 +1,261 @@
+/* Function return value location for Linux/mips ABI.
+   Copyright (C) 2005 Red Hat, Inc.
+   Copyright (C) 2023 CIP United Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <dwarf.h>
+#include <string.h>
+#include <elf.h>
+#include <stdio.h>
+
+#define BACKEND mips_
+#include "libebl_CPU.h"
+#include "libdwP.h"
+
+/* All the possible MIPS ARCHs. */
+enum mips_arch
+  {
+    MIPS_ARCH_UNKNOWN = 0,
+    MIPS_ARCH_32,
+    MIPS_ARCH_64,
+    MIPS_ARCH_LAST
+  };
+
+/* Find the mips ARCH of the current file */
+enum mips_arch find_mips_arch(Elf *elf)
+{
+  GElf_Ehdr ehdr_mem;
+  GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem);
+
+  if (ehdr == NULL)
+    return MIPS_ARCH_LAST;
+
+  GElf_Word elf_flags = ehdr->e_flags;
+
+  /* Check elf_flags to see if it specifies the ARCH being used.  */
+  switch ((elf_flags & EF_MIPS_ARCH))
+    {
+    case E_MIPS_ARCH_32:
+    case EF_MIPS_ARCH_32R2:
+    case E_MIPS_ARCH_32R6:
+      return MIPS_ARCH_32;
+    case E_MIPS_ARCH_64:
+    case EF_MIPS_ARCH_64R2:
+    case E_MIPS_ARCH_64R6:
+      return MIPS_ARCH_64;
+    default:
+      return MIPS_ARCH_32;
+    }
+
+  return MIPS_ARCH_UNKNOWN;
+}
+
+unsigned int
+mips_arch_regsize (enum mips_arch arch)
+{
+  switch (arch)
+    {
+    case MIPS_ARCH_32:
+      return 4;
+    case MIPS_ARCH_64:
+      return 8;
+    case MIPS_ARCH_UNKNOWN:
+    case MIPS_ARCH_LAST:
+    default:
+      return 0;
+    }
+}
+
+/* $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)
+{
+  /* First find the ARCH used by the elf object */
+  enum mips_arch arch = find_mips_arch(functypedie->cu->dbg->elf);
+  /* Something went seriously wrong while trying to figure out the ARCH */
+  if (arch == MIPS_ARCH_LAST)
+    return -1;
+
+  /* We couldn't identify the ARCH, but the file seems valid */
+  if (arch == MIPS_ARCH_UNKNOWN)
+    return -3;
+
+  unsigned int regsize = mips_arch_regsize (arch);
+  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 && arch == MIPS_ARCH_32)
+                  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:
+      /* XXX TODO: Can't handle structure return with other ABI's yet :-/ */
+      if ((arch != MIPS_ARCH_32) && (arch != MIPS_ARCH_64))
+        return -2;
+
+      *locp = loc_aggregate;
+      return nloc_aggregate;
+    }
+
+  /* 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;
+}
-- 
2.30.2

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 0/5] Add support for MIPS
  2023-04-11  8:12 [PATCH 0/5] Add support for MIPS Ying Huang
                   ` (4 preceding siblings ...)
  2023-04-11  8:12 ` [PATCH 5/5] backends: Fix run-native-test.sh and run-funcretval++11.sh run fail " Ying Huang
@ 2023-05-04  2:24 ` 黄莺
  5 siblings, 0 replies; 30+ messages in thread
From: 黄莺 @ 2023-05-04  2:24 UTC (permalink / raw)
  To: Luke Diamand via Elfutils-devel; +Cc: 苏运强

[-- Attachment #1: Type: text/plain, Size: 366 bytes --]

ping
> 
> From:"Ying Huang"<ying.huang@oss.cipunited.com>
> Date:Tue, Apr 11, 2023, 16:12
> Subject:[PATCH 0/5] Add support for MIPS
> To:<elfutils-devel@sourceware.org>
> This is a series of modifications about MIPS.
> Support src/readelf, strip, unstrip, elflint, objdump related tools.
> Pass all previous test cases that failed due to MIPS non-support.

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 1/5] strip: Adapt src/strip -o -f on mips
  2023-04-11  8:12 ` [PATCH 1/5] strip: Adapt src/strip -o -f on mips Ying Huang
@ 2023-05-09 15:15   ` Mark Wielaard
  2023-05-16  6:38     ` Ying Huang
                       ` (2 more replies)
  0 siblings, 3 replies; 30+ messages in thread
From: Mark Wielaard @ 2023-05-09 15:15 UTC (permalink / raw)
  To: ying.huang, elfutils-devel

Hi,

On Tue, 2023-04-11 at 16:12 +0800, Ying Huang wrote:
> From: Ying Huang <ying.huang@oss.cipunited.com>
> 
> 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.

Is there a spec that describes this?

I see you adjusted elf.h to include:

+#define ELF64_MIPS_R_TYPE(i)		((i) & 0xff)
+#define ELF64_MIPS_R_TYPE2(i)           (((i) >> 8) & 0xff)
+#define ELF64_MIPS_R_TYPE3(i)           (((i) >> 16) & 0xff)

And various new relocation types for MIPS variants.
Our elf.h comes from the glibc project. Have you also submitted these
changes to libc-alpha@sourceware.org ?

>   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.

Where do these segfaults show up?

>   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.

It feels like this is in the wrong place and doesn't take into account
whether the program itself is running on a big or little endian
machine.

Maybe I am misunderstanding why this conversion is needed always. But I
would have expected a specific conversion function for MIPS for
ELF_T_REL and/or ELF_T_RELA (which are currently generic).

Cheers,

Mark

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 2/5] readelf: Adapt src/readelf -h/-S/-r/-w/-l/-d/-a on mips
  2023-04-11  8:12 ` [PATCH 2/5] readelf: Adapt src/readelf -h/-S/-r/-w/-l/-d/-a " Ying Huang
@ 2023-05-11 14:31   ` Mark Wielaard
  2023-05-16  8:01     ` Ying Huang
  2023-07-24  8:35     ` Ying Huang
  0 siblings, 2 replies; 30+ messages in thread
From: Mark Wielaard @ 2023-05-11 14:31 UTC (permalink / raw)
  To: ying.huang, elfutils-devel

Hi,

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

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

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

OK.

> diff --git a/backends/mips_attrs.c b/backends/mips_attrs.c
> new file mode 100644
> index 00000000..1419814e
> --- /dev/null
> +++ b/backends/mips_attrs.c
> @@ -0,0 +1,107 @@
> +/* Object attribute tags for MIPS.
> +   Copyright (C) 2023 CIP United Inc.
> +   This file is part of elfutils.
> +
> +   This file is free software; you can redistribute it and/or modify
> +   it under the terms of either
> +
> +     * the GNU Lesser General Public License as published by the Free
> +       Software Foundation; either version 3 of the License, or (at
> +       your option) any later version
> +
> +   or
> +
> +     * the GNU General Public License as published by the Free
> +       Software Foundation; either version 2 of the License, or (at
> +       your option) any later version
> +
> +   or both in parallel, as here.
> +
> +   elfutils is distributed in the hope that it will be useful, but
> +   WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   General Public License for more details.
> +
> +   You should have received copies of the GNU General Public License and
> +   the GNU Lesser General Public License along with this program.  If
> +   not, see <http://www.gnu.org/licenses/>.  */
> +
> +#ifdef HAVE_CONFIG_H
> +# include <config.h>
> +#endif
> +
> +#include <string.h>
> +#include <dwarf.h>
> +
> +#define BACKEND arm_

You mean mips_

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

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

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

OK

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

OK
But see below for also hooking reloc_type_check and reloc_type_name.

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

OK

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

OK

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

OK

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

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

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

OK

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

OK

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

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

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

Likewise for hooking reloc_type_name.

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

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

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

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

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

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

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

Likewise.

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

And again.

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

And again. Adding testcase would be nice.

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

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

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

Cheers,

Mark

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 3/5] elflint: Fix invalid type of relocation info and other issues on mips
  2023-04-11  8:12 ` [PATCH 3/5] elflint: Fix invalid type of relocation info and other issues " Ying Huang
@ 2023-05-11 15:59   ` Mark Wielaard
  2023-05-17  9:14     ` Ying Huang
  0 siblings, 1 reply; 30+ messages in thread
From: Mark Wielaard @ 2023-05-11 15:59 UTC (permalink / raw)
  To: ying.huang, elfutils-devel

Hi,

On Tue, 2023-04-11 at 16:12 +0800, Ying Huang wrote:
> From: Ying Huang <ying.huang@oss.cipunited.com>
> 
> add some check related functions
> ---
>  backends/mips_init.c      |  3 +++
>  backends/mips_symbol.c    | 33 +++++++++++++++++++++++++++++++++
>  libebl/eblrelocvaliduse.c |  8 ++++++--
>  src/elflint.c             | 23 ++++++++++++++++++++---
>  4 files changed, 62 insertions(+), 5 deletions(-)
> 
> diff --git a/backends/mips_init.c b/backends/mips_init.c
> index 5bba822b..4c2f21b9 100644
> --- a/backends/mips_init.c
> +++ b/backends/mips_init.c
> @@ -51,6 +51,9 @@ mips_init (Elf *elf __attribute__ ((unused)),
>    HOOK (eh, segment_type_name);
>    HOOK (eh, dynamic_tag_check);
>    HOOK (eh, dynamic_tag_name);
> +  HOOK (eh, machine_section_flag_check);
>    HOOK (eh, check_object_attribute);
> +  HOOK (eh, check_special_symbol);
> +  HOOK (eh, check_reloc_target_type);
>    return eh;
>  }

OK. But see below for hooking reloc_valid_use

> diff --git a/backends/mips_symbol.c b/backends/mips_symbol.c
> index e760d58d..8787fcee 100644
> --- a/backends/mips_symbol.c
> +++ b/backends/mips_symbol.c
> @@ -158,6 +158,39 @@ 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);
> +}

OK

> +/* 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);
> +}

Could you add a comment why .got and .bss are special in this case?

> +/* 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)) == 0);
> +}

OK. But see below for checking other SHF_MIPS flags.

>  /* Check whether machine flags are valid.  */
>  bool
>  mips_machine_flag_check (GElf_Word flags)
> diff --git a/libebl/eblrelocvaliduse.c b/libebl/eblrelocvaliduse.c
> index f0bed345..44b8d300 100644
> --- a/libebl/eblrelocvaliduse.c
> +++ b/libebl/eblrelocvaliduse.c
> @@ -32,10 +32,14 @@
>  #endif
>  
>  #include <libeblP.h>
> -
> +#include <libelfP.h>
>  
>  bool
>  ebl_reloc_valid_use (Ebl *ebl, int reloc)
>  {
> -  return ebl != NULL ? ebl->reloc_valid_use (ebl->elf, reloc) : false;
> +  int relocNew = reloc;
> +  GElf_Ehdr ehdr;
> +  if(ebl->elf->class == ELFCLASS64 && gelf_getehdr(ebl->elf, &ehdr) != NULL && ehdr.e_machine == EM_MIPS)
> +    relocNew = ELF64_MIPS_R_TYPE(reloc);
> +  return ebl != NULL ? ebl->reloc_valid_use (ebl->elf, relocNew) : false;
>  }

This should be a mips reloc_valid_use hook.

> diff --git a/src/elflint.c b/src/elflint.c
> index dd42dcb4..04f1ee92 100644
> --- a/src/elflint.c
> +++ b/src/elflint.c
> @@ -935,7 +935,10 @@ section [%2d] '%s': symbol %zu (%s): non-local symbol outside range described in
>  	}
>  
>        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_LINK") != 0
> +	  && strcmp (name, "_DYNAMIC_LINKING") != 0)

Could you add a comment here about both symbols not being local on
MIPS?

>  	ERROR (_("\
>  section [%2d] '%s': symbol %zu (%s): non-local section symbol\n"),
>  	       idx, section_name (ebl, idx), cnt, name);
> @@ -3789,6 +3792,12 @@ cannot get section header for section [%2zu] '%s': %s\n"),
>  		    && 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;
> +		  }

OK. You don't need explicit brackets here

>  		/* 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
> @@ -3953,8 +3962,16 @@ section [%2zu] '%s': size not multiple of entry size\n"),
>  	      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 (ehdr->e_machine == EM_MIPS)
> +	        {
> +	          if(sh_flags == SHF_MIPS_NOSTRIP || sh_flags == SHF_MIPS_LOCAL
> +		   || sh_flags == SHF_MIPS_NAMES || sh_flags == SHF_MIPS_NODUPE)
> +	            sh_flags &= ~shdr->sh_flags;
> +	        }
> +	    }
>  	  if (sh_flags != 0)
>  	    ERROR (_("section [%2zu] '%s' contains unknown flag(s)"
>  			    " %#" PRIx64 "\n"),

Can this be checked with the machine_section_flag_check hook?

Thanks,

Mark

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 4/5] stack: Fix stack unwind failure on mips
  2023-04-11  8:12 ` [PATCH 4/5] stack: Fix stack unwind failure " Ying Huang
@ 2023-05-11 16:07   ` Mark Wielaard
  2023-05-18  6:14     ` Ying Huang
  0 siblings, 1 reply; 30+ messages in thread
From: Mark Wielaard @ 2023-05-11 16:07 UTC (permalink / raw)
  To: ying.huang, elfutils-devel

Hi,

On Tue, 2023-04-11 at 16:12 +0800, Ying Huang wrote:
> From: Ying Huang <ying.huang@oss.cipunited.com>
> 
> add abi_cfi, set_initial_registers_tid, unwind on mips.
> "./src/stack -p PID" can show stack information
> ---
>  backends/Makefile.am    |  3 +-
>  backends/mips_cfi.c     | 68 +++++++++++++++++++++++++++++++++
>  backends/mips_init.c    |  4 ++
>  backends/mips_initreg.c | 70 ++++++++++++++++++++++++++++++++++
>  backends/mips_unwind.c  | 84 +++++++++++++++++++++++++++++++++++++++++
>  5 files changed, 228 insertions(+), 1 deletion(-)
>  create mode 100644 backends/mips_cfi.c
>  create mode 100644 backends/mips_initreg.c
>  create mode 100644 backends/mips_unwind.c

This looks good. Just two questions below.

> diff --git a/backends/Makefile.am b/backends/Makefile.am
> index 428a1a03..ddc31c9d 100644
> --- a/backends/Makefile.am
> +++ b/backends/Makefile.am
> @@ -100,7 +100,8 @@ loongarch_SRCS = loongarch_init.c loongarch_symbol.c
>  
>  arc_SRCS = arc_init.c arc_symbol.c
>  
> -mips_SRCS = mips_init.c mips_symbol.c mips_attrs.c
> +mips_SRCS = mips_init.c mips_symbol.c mips_attrs.c mips_initreg.c \
> +	    mips_cfi.c mips_unwind.c

OK
 
>  libebl_backends_a_SOURCES = $(i386_SRCS) $(sh_SRCS) $(x86_64_SRCS) \
>  			    $(ia64_SRCS) $(alpha_SRCS) $(arm_SRCS) \
> diff --git a/backends/mips_cfi.c b/backends/mips_cfi.c
> new file mode 100644
> index 00000000..77132cc1
> --- /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) 2023 CIP United Inc.
> +   This file is part of elfutils.
> +
> +   This file is free software; you can redistribute it and/or modify
> +   it under the terms of either
> +
> +     * the GNU Lesser General Public License as published by the Free
> +       Software Foundation; either version 3 of the License, or (at
> +       your option) any later version
> +
> +   or
> +
> +     * the GNU General Public License as published by the Free
> +       Software Foundation; either version 2 of the License, or (at
> +       your option) any later version
> +
> +   or both in parallel, as here.
> +
> +   elfutils is distributed in the hope that it will be useful, but
> +   WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   General Public License for more details.
> +
> +   You should have received copies of the GNU General Public License and
> +   the GNU Lesser General Public License along with this program.  If
> +   not, see <http://www.gnu.org/licenses/>.  */
> +
> +#ifdef HAVE_CONFIG_H
> +# include <config.h>
> +#endif
> +
> +#include <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 = -4;
> +
> +  abi_info->return_address_register = 31; /* %ra */
> +
> +  return 0;
> +}

Looks good, but do you have a reference to the ABI docs would be nice
to add an URL as comment for people to double check.

> diff --git a/backends/mips_init.c b/backends/mips_init.c
> index 4c2f21b9..3caa9fee 100644
> --- a/backends/mips_init.c
> +++ b/backends/mips_init.c
> @@ -55,5 +55,9 @@ mips_init (Elf *elf __attribute__ ((unused)),
>    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 = 32;
>    return eh;
>  }

OK

> diff --git a/backends/mips_initreg.c b/backends/mips_initreg.c
> new file mode 100644
> index 00000000..31b8de13
> --- /dev/null
> +++ b/backends/mips_initreg.c
> @@ -0,0 +1,70 @@
> +/* Fetch live process registers from TID.
> +   Copyright (C) 2023 CIP United Inc.
> +   This file is part of elfutils.
> +
> +   This file is free software; you can redistribute it and/or modify
> +   it under the terms of either
> +
> +     * the GNU Lesser General Public License as published by the Free
> +       Software Foundation; either version 3 of the License, or (at
> +       your option) any later version
> +
> +   or
> +
> +     * the GNU General Public License as published by the Free
> +       Software Foundation; either version 2 of the License, or (at
> +       your option) any later version
> +
> +   or both in parallel, as here.
> +
> +   elfutils is distributed in the hope that it will be useful, but
> +   WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   General Public License for more details.
> +
> +   You should have received copies of the GNU General Public License and
> +   the GNU Lesser General Public License along with this program.  If
> +   not, see <http://www.gnu.org/licenses/>.  */
> +
> +#ifdef HAVE_CONFIG_H
> +# include <config.h>
> +#endif
> +
> +#include <stdlib.h>
> +#if (defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__)) && defined(__linux__)
> +# include <sys/user.h>
> +# include <sys/ptrace.h>
> +#endif
> +
> +#define BACKEND mips_
> +#include "libebl_CPU.h"
> +#include <stdio.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 {
> +    uint64_t regs[32];
> +    uint64_t lo;
> +    uint64_t hi;
> +    uint64_t pc;
> +    uint64_t badvaddr;
> +    uint64_t cause;
> +    uint64_t status;
> +};

Isn't this defined in some standard (or glibc/linux specific) header?

> +  struct pt_regs gregs;
> +  if (ptrace (PTRACE_GETREGS, tid, 0, &gregs) != 0)
> +    return false;
> +  if (! setfunc (-1, 1, (Dwarf_Word *) &gregs.pc, arg))
> +    return false;
> +  return setfunc (0, 32, (Dwarf_Word *) &gregs.regs[0], arg);
> +#endif /* __mips__ */
> +}

OK

> diff --git a/backends/mips_unwind.c b/backends/mips_unwind.c
> new file mode 100644
> index 00000000..d09db3a9
> --- /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) 2023 CIP United Inc.
> +   This file is part of elfutils.
> +
> +   This file is free software; you can redistribute it and/or modify
> +   it under the terms of either
> +
> +     * the GNU Lesser General Public License as published by the Free
> +       Software Foundation; either version 3 of the License, or (at
> +       your option) any later version
> +
> +   or
> +
> +     * the GNU General Public License as published by the Free
> +       Software Foundation; either version 2 of the License, or (at
> +       your option) any later version
> +
> +   or both in parallel, as here.
> +
> +   elfutils is distributed in the hope that it will be useful, but
> +   WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   General Public License for more details.
> +
> +   You should have received copies of the GNU General Public License and
> +   the GNU Lesser General Public License along with this program.  If
> +   not, see <http://www.gnu.org/licenses/>.  */
> +
> +#ifdef HAVE_CONFIG_H
> +# include <config.h>
> +#endif
> +
> +#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;
> +}

Looks good.

Thanks,

Mark


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 5/5] backends: Fix run-native-test.sh and run-funcretval++11.sh run fail on mips
  2023-04-11  8:12 ` [PATCH 5/5] backends: Fix run-native-test.sh and run-funcretval++11.sh run fail " Ying Huang
@ 2023-05-11 16:38   ` Mark Wielaard
  2023-05-18  9:06     ` Ying Huang
  0 siblings, 1 reply; 30+ messages in thread
From: Mark Wielaard @ 2023-05-11 16:38 UTC (permalink / raw)
  To: ying.huang, elfutils-devel

Hi,

On Tue, 2023-04-11 at 16:12 +0800, Ying Huang wrote:
> From: Ying Huang <ying.huang@oss.cipunited.com>
> 
> add register_info, return_value_location function on mips
> ---
>  backends/Makefile.am   |   2 +-
>  backends/mips_init.c   |   2 +
>  backends/mips_regs.c   | 109 +++++++++++++++++
>  backends/mips_retval.c | 261 +++++++++++++++++++++++++++++++++++++++++
>  4 files changed, 373 insertions(+), 1 deletion(-)
>  create mode 100644 backends/mips_regs.c
>  create mode 100644 backends/mips_retval.c
> 
> diff --git a/backends/Makefile.am b/backends/Makefile.am
> index ddc31c9d..5453f787 100644
> --- a/backends/Makefile.am
> +++ b/backends/Makefile.am
> @@ -101,7 +101,7 @@ loongarch_SRCS = loongarch_init.c loongarch_symbol.c
>  arc_SRCS = arc_init.c arc_symbol.c
>  
>  mips_SRCS = mips_init.c mips_symbol.c mips_attrs.c mips_initreg.c \
> -	    mips_cfi.c mips_unwind.c
> +	    mips_cfi.c mips_unwind.c mips_regs.c mips_retval.c

OK.
 
>  libebl_backends_a_SOURCES = $(i386_SRCS) $(sh_SRCS) $(x86_64_SRCS) \
>  			    $(ia64_SRCS) $(alpha_SRCS) $(arm_SRCS) \
> diff --git a/backends/mips_init.c b/backends/mips_init.c
> index 3caa9fee..7ca93314 100644
> --- a/backends/mips_init.c
> +++ b/backends/mips_init.c
> @@ -58,6 +58,8 @@ mips_init (Elf *elf __attribute__ ((unused)),
>    HOOK (eh, set_initial_registers_tid);
>    HOOK (eh, abi_cfi);
>    HOOK (eh, unwind);
> +  HOOK (eh, register_info);
> +  HOOK (eh, return_value_location);
>    eh->frame_nregs = 32;
>    return eh;
>  }

OK

> diff --git a/backends/mips_regs.c b/backends/mips_regs.c
> new file mode 100644
> index 00000000..733caeee
> --- /dev/null
> +++ b/backends/mips_regs.c
> @@ -0,0 +1,109 @@
> +/* Register names and numbers for mips DWARF.
> +   Copyright (C) 2006 Red Hat, Inc.
> +   Copyright (C) 2023 CIP United Inc.
> +   This file is part of elfutils.
> +
> +   This file is free software; you can redistribute it and/or modify
> +   it under the terms of either
> +
> +     * the GNU Lesser General Public License as published by the Free
> +       Software Foundation; either version 3 of the License, or (at
> +       your option) any later version
> +
> +   or
> +
> +     * the GNU General Public License as published by the Free
> +       Software Foundation; either version 2 of the License, or (at
> +       your option) any later version
> +
> +   or both in parallel, as here.
> +
> +   elfutils is distributed in the hope that it will be useful, but
> +   WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   General Public License for more details.
> +
> +   You should have received copies of the GNU General Public License and
> +   the GNU Lesser General Public License along with this program.  If
> +   not, see <http://www.gnu.org/licenses/>.  */
> +
> +#ifdef HAVE_CONFIG_H
> +# include <config.h>
> +#endif
> +
> +#include <assert.h>
> +#include <dwarf.h>
> +#include <string.h>
> +
> +#define BACKEND mips_
> +#include "libebl_CPU.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 66;
> +
> +  if (regno < 0 || regno > 65 || namelen < 4)
> +    return -1;
> +
> +  *prefix = "$";
> +  
> +  if (regno < 32)
> +    {
> +      *setname = "integer";
> +      *type = DW_ATE_signed;
> +      *bits = 32;
> +      if (regno < 32 + 10)
> +      {
> +        name[0] = regno + '0';
> +	namelen = 1;
> +      }
> +      else
> +      {
> +        name[0] = (regno / 10) + '0';
> +	name[1] = (regno % 10) + '0';
> +	namelen = 2;
> +      }
> +    }
> +  else if (regno < 64)
> +    {
> +      *setname = "FPU";
> +      *type = DW_ATE_float;
> +      *bits = 32;
> +      name[0] = 'f';
> +      if (regno < 32 + 10)
> +      {
> +        name[1] = (regno - 32) + '0';
> +	namelen = 2;
> +      }
> +      else
> +      {
> +        name[1] = (regno - 32) / 10 + '0';
> +	name[2] = (regno - 32) % 10 + '0';
> +	namelen = 3;
> +      }
> +    }
> +  else if (regno == 64)
> +    {
> +      *type = DW_ATE_signed;
> +      *bits = 32;
> +      name[0] = 'h';
> +      name[1] = 'i';
> +      namelen = 2;
> +    }
> +  else
> +    {
> +      *type = DW_ATE_signed;
> +      *bits = 32;
> +      name[0] = 'l';
> +      name[1] = 'o';
> +      namelen = 2;
> +    }
> +
> +  name[namelen++] = '\0';
> +  return namelen;
> +}

OK, but indentation seems slightly off. space vs tabs?

> diff --git a/backends/mips_retval.c b/backends/mips_retval.c
> new file mode 100644
> index 00000000..fd9aaefa
> --- /dev/null
> +++ b/backends/mips_retval.c
> @@ -0,0 +1,261 @@
> +/* Function return value location for Linux/mips ABI.
> +   Copyright (C) 2005 Red Hat, Inc.
> +   Copyright (C) 2023 CIP United Inc.
> +   This file is part of elfutils.
> +
> +   This file is free software; you can redistribute it and/or modify
> +   it under the terms of either
> +
> +     * the GNU Lesser General Public License as published by the Free
> +       Software Foundation; either version 3 of the License, or (at
> +       your option) any later version
> +
> +   or
> +
> +     * the GNU General Public License as published by the Free
> +       Software Foundation; either version 2 of the License, or (at
> +       your option) any later version
> +
> +   or both in parallel, as here.
> +
> +   elfutils is distributed in the hope that it will be useful, but
> +   WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   General Public License for more details.
> +
> +   You should have received copies of the GNU General Public License and
> +   the GNU Lesser General Public License along with this program.  If
> +   not, see <http://www.gnu.org/licenses/>.  */
> +
> +#ifdef HAVE_CONFIG_H
> +# include <config.h>
> +#endif
> +
> +#include <assert.h>
> +#include <dwarf.h>
> +#include <string.h>
> +#include <elf.h>
> +#include <stdio.h>
> +
> +#define BACKEND mips_
> +#include "libebl_CPU.h"
> +#include "libdwP.h"
> +
> +/* All the possible MIPS ARCHs. */
> +enum mips_arch
> +  {
> +    MIPS_ARCH_UNKNOWN = 0,
> +    MIPS_ARCH_32,
> +    MIPS_ARCH_64,
> +    MIPS_ARCH_LAST
> +  };
> +
> +/* Find the mips ARCH of the current file */
> +enum mips_arch find_mips_arch(Elf *elf)
> +{
> +  GElf_Ehdr ehdr_mem;
> +  GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem);
> +
> +  if (ehdr == NULL)
> +    return MIPS_ARCH_LAST;
> +
> +  GElf_Word elf_flags = ehdr->e_flags;
> +
> +  /* Check elf_flags to see if it specifies the ARCH being used.  */
> +  switch ((elf_flags & EF_MIPS_ARCH))
> +    {
> +    case E_MIPS_ARCH_32:
> +    case EF_MIPS_ARCH_32R2:
> +    case E_MIPS_ARCH_32R6:
> +      return MIPS_ARCH_32;
> +    case E_MIPS_ARCH_64:
> +    case EF_MIPS_ARCH_64R2:
> +    case E_MIPS_ARCH_64R6:
> +      return MIPS_ARCH_64;
> +    default:
> +      return MIPS_ARCH_32;
> +    }
> +
> +  return MIPS_ARCH_UNKNOWN;
> +}
>
> +unsigned int
> +mips_arch_regsize (enum mips_arch arch)
> +{
> +  switch (arch)
> +    {
> +    case MIPS_ARCH_32:
> +      return 4;
> +    case MIPS_ARCH_64:
> +      return 8;
> +    case MIPS_ARCH_UNKNOWN:
> +    case MIPS_ARCH_LAST:
> +    default:
> +      return 0;
> +    }
> +}

So this is different from checking ELFCLASS32/64?

> +/* $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)
> +{
> +  /* First find the ARCH used by the elf object */
> +  enum mips_arch arch = find_mips_arch(functypedie->cu->dbg->elf);
> +  /* Something went seriously wrong while trying to figure out the ARCH */
> +  if (arch == MIPS_ARCH_LAST)
> +    return -1;
> +
> +  /* We couldn't identify the ARCH, but the file seems valid */
> +  if (arch == MIPS_ARCH_UNKNOWN)
> +    return -3;
> +
> +  unsigned int regsize = mips_arch_regsize (arch);
> +  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 && arch == MIPS_ARCH_32)
> +                  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:
> +      /* XXX TODO: Can't handle structure return with other ABI's yet :-/ */
> +      if ((arch != MIPS_ARCH_32) && (arch != MIPS_ARCH_64))
> +        return -2;
> +
> +      *locp = loc_aggregate;
> +      return nloc_aggregate;
> +    }
> +
> +  /* 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;
> +}

OK. This looks plausible. Would be good to have a reference to the
actual calling convention.

Thanks,

Mark

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 1/5] strip: Adapt src/strip -o -f on mips
  2023-05-09 15:15   ` Mark Wielaard
@ 2023-05-16  6:38     ` Ying Huang
  2023-05-21 21:13       ` Mark Wielaard
  2023-05-16  6:46     ` Ying Huang
  2023-05-16  8:05     ` [EXTERNAL] " Luke Diamand
  2 siblings, 1 reply; 30+ messages in thread
From: Ying Huang @ 2023-05-16  6:38 UTC (permalink / raw)
  To: Mark Wielaard, elfutils-devel; +Cc: yunqiang.su

[-- Attachment #1: Type: text/plain, Size: 2624 bytes --]

Hi,

在 2023/5/9 23:15, Mark Wielaard 写道:
> Hi,
>
> On Tue, 2023-04-11 at 16:12 +0800, Ying Huang wrote:
>> From: Ying Huang <ying.huang@oss.cipunited.com>
>>
>> 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.
> Is there a spec that describes this?
   

 references:

    https://www.linux-mips.org/pub/linux/mips/doc/ABI/elf64-2.4.pdf

    Page40 && Page41

>
> I see you adjusted elf.h to include:
>
> +#define ELF64_MIPS_R_TYPE(i)		((i) & 0xff)
> +#define ELF64_MIPS_R_TYPE2(i)           (((i) >> 8) & 0xff)
> +#define ELF64_MIPS_R_TYPE3(i)           (((i) >> 16) & 0xff)
>
> And various new relocation types for MIPS variants.
> Our elf.h comes from the glibc project. Have you also submitted these
> changes to libc-alpha@sourceware.org ?
    Has submitted.

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

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

>
>>   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.
> Where do these segfaults show up?

>
>>   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.
    Has tested on big/little endian machine with big/little endian ELF file, all were OK.
> It feels like this is in the wrong place and doesn't take into account
> whether the program itself is running on a big or little endian
> machine.
>
> Maybe I am misunderstanding why this conversion is needed always. But I
> would have expected a specific conversion function for MIPS for
> ELF_T_REL and/or ELF_T_RELA (which are currently generic).
>
> Cheers,
>
> Mark
    1.Considering that some people directly use the original data instead of the interface function gelf_getrela;

    2.Because there is only one parameter, so can not modify the macro ELF64_R_TYPE;

    3.If the mips interface function is added, other packages using libelf will not be compatible with mips, and the place where gelf_getrela is used need be modified.

    Where do you think is the most suitable place to do mips conversion?

Thanks,

Ying

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 1/5] strip: Adapt src/strip -o -f on mips
  2023-05-09 15:15   ` Mark Wielaard
  2023-05-16  6:38     ` Ying Huang
@ 2023-05-16  6:46     ` Ying Huang
  2023-05-16  7:34       ` Ying Huang
  2023-05-16  8:05     ` [EXTERNAL] " Luke Diamand
  2 siblings, 1 reply; 30+ messages in thread
From: Ying Huang @ 2023-05-16  6:46 UTC (permalink / raw)
  To: Mark Wielaard, elfutils-devel

[-- Attachment #1: Type: text/plain, Size: 422 bytes --]

HI,

>>   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.
> Where do these segfaults show up?
    The screenshot of the segment error was not uploaded successfully in the last email, upload again.

Thanks,

YIng

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 1/5] strip: Adapt src/strip -o -f on mips
  2023-05-16  6:46     ` Ying Huang
@ 2023-05-16  7:34       ` Ying Huang
  2023-05-21 21:14         ` Mark Wielaard
  0 siblings, 1 reply; 30+ messages in thread
From: Ying Huang @ 2023-05-16  7:34 UTC (permalink / raw)
  To: Mark Wielaard, elfutils-devel

[-- Attachment #1: Type: text/plain, Size: 653 bytes --]

在 2023/5/16 14:46, Ying Huang 写道:
>
> HI,
>
> >> 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.
> > Where do these segfaults show up?
>     The screenshot of the segment error was not uploaded successfully in the last email, upload again.
>
> Thanks,
>
> YIng
>

huangying@Sleepygon:~/elf/elfutils_4$ src/elflint src/nm.o
Segmentation fault
huangying@Sleepygon:~/elf/elfutils_4$ src/elflint src/strip.o
Segmentation fault

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 2/5] readelf: Adapt src/readelf -h/-S/-r/-w/-l/-d/-a on mips
  2023-05-11 14:31   ` Mark Wielaard
@ 2023-05-16  8:01     ` Ying Huang
  2023-07-24  8:35     ` Ying Huang
  1 sibling, 0 replies; 30+ messages in thread
From: Ying Huang @ 2023-05-16  8:01 UTC (permalink / raw)
  To: Mark Wielaard, elfutils-devel; +Cc: yunqiang.su

[-- Attachment #1: Type: text/plain, Size: 11967 bytes --]

Hi,

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

    Yes, it should be mips_, thanks!


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


    OK, I would add hook for reloc_type_check and reloc_type_name.


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

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

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

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

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


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

  

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

   

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


    OK, I would like to add testcase.

    Both support.


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

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


Thanks,

Ying

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [EXTERNAL] Re: [PATCH 1/5] strip: Adapt src/strip -o -f on mips
  2023-05-09 15:15   ` Mark Wielaard
  2023-05-16  6:38     ` Ying Huang
  2023-05-16  6:46     ` Ying Huang
@ 2023-05-16  8:05     ` Luke Diamand
  2 siblings, 0 replies; 30+ messages in thread
From: Luke Diamand @ 2023-05-16  8:05 UTC (permalink / raw)
  To: Mark Wielaard, ying.huang, elfutils-devel



On 09/05/2023 16:15, Mark Wielaard wrote:
> Hi,
> 
> On Tue, 2023-04-11 at 16:12 +0800, Ying Huang wrote:
>> From: Ying Huang <ying.huang@oss.cipunited.com>
>>
>> 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.
> 
> Is there a spec that describes this?
> 
> I see you adjusted elf.h to include:
> 
> +#define ELF64_MIPS_R_TYPE(i)		((i) & 0xff)
> +#define ELF64_MIPS_R_TYPE2(i)           (((i) >> 8) & 0xff)
> +#define ELF64_MIPS_R_TYPE3(i)           (((i) >> 16) & 0xff)
> 

Is this patch intended to support 32 bit MIPS (and MIPSEL) ?

For me it did not work but I could see if I can add that in.

(From a very long time ago, I have some patches based on the debian MIPS 
support but I never managed to find time to upstream them, so this is 
great to finally see!)

Luke


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 3/5] elflint: Fix invalid type of relocation info and other issues on mips
  2023-05-11 15:59   ` Mark Wielaard
@ 2023-05-17  9:14     ` Ying Huang
  0 siblings, 0 replies; 30+ messages in thread
From: Ying Huang @ 2023-05-17  9:14 UTC (permalink / raw)
  To: Mark Wielaard, elfutils-devel; +Cc: yunqiang.su

[-- Attachment #1: Type: text/plain, Size: 8226 bytes --]

Hi,

在 2023/5/11 23:59, Mark Wielaard 写道:
> Hi,
>
> On Tue, 2023-04-11 at 16:12 +0800, Ying Huang wrote:
>> From: Ying Huang <ying.huang@oss.cipunited.com>
>>
>> add some check related functions
>> ---
>>  backends/mips_init.c      |  3 +++
>>  backends/mips_symbol.c    | 33 +++++++++++++++++++++++++++++++++
>>  libebl/eblrelocvaliduse.c |  8 ++++++--
>>  src/elflint.c             | 23 ++++++++++++++++++++---
>>  4 files changed, 62 insertions(+), 5 deletions(-)
>>
>> diff --git a/backends/mips_init.c b/backends/mips_init.c
>> index 5bba822b..4c2f21b9 100644
>> --- a/backends/mips_init.c
>> +++ b/backends/mips_init.c
>> @@ -51,6 +51,9 @@ mips_init (Elf *elf __attribute__ ((unused)),
>>    HOOK (eh, segment_type_name);
>>    HOOK (eh, dynamic_tag_check);
>>    HOOK (eh, dynamic_tag_name);
>> +  HOOK (eh, machine_section_flag_check);
>>    HOOK (eh, check_object_attribute);
>> +  HOOK (eh, check_special_symbol);
>> +  HOOK (eh, check_reloc_target_type);
>>    return eh;
>>  }
> OK. But see below for hooking reloc_valid_use

     OK, I would add hook reloc_valid_use.


>> +/* 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);
>> +}
> Could you add a comment why .got and .bss are special in this case?

    raw code:

    huangying@Sleepygon:~/elf/elfutils_4$ src/elflint  src/nm
    section [38] '.symtab': symbol 781 (_gp): st_value out of bounds
    section [38] '.symtab': _DYNAMIC symbol size 0 does not match dynamic segment size 624
    section [38] '.symtab': _GLOBAL_OFFSET_TABLE_ symbol size 0 does not match .got section size 3736

    huangying@Sleepygon:~/elf/elfutils_4$ src/elflint --gnu src/nm
    section [38] '.symtab': symbol 781 (_gp): st_value out of bounds

    After add '.got':

    huangying@Sleepygon:~/elf/elfutils_4$ src/elflint  src/nm
    section [38] '.symtab': _DYNAMIC symbol size 0 does not match dynamic segment size 624
    section [38] '.symtab': symbol 912 (_fbss): st_value out of bounds
    section [38] '.symtab': symbol 1160 (__bss_start): st_value out of bounds

    huangying@Sleepygon:~/elf/elfutils_4$ src/elflint  --gnu src/nm
    section [38] '.symtab': symbol 912 (_fbss): st_value out of bounds

    After add '.bss':

    huangying@Sleepygon:~/elf/elfutils_4$ src/elflint  src/nm
    section [38] '.symtab': _DYNAMIC symbol size 0 does not match dynamic segment size 624

    huangying@Sleepygon:~/elf/elfutils_4$ src/elflint  --gnu src/nm
    No errors

    And also has error , but make check is OK.

   

>
>> +/* 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)) == 0);
>> +}
> OK. But see below for checking other SHF_MIPS flags.

    OK, add it:

diff --git a/backends/mips_symbol.c b/backends/mips_symbol.c
index 8787fcee..f4dee731 100644
--- a/backends/mips_symbol.c
+++ b/backends/mips_symbol.c
@@ -188,7 +188,11 @@ mips_machine_section_flag_check (GElf_Xword sh_flags)
   return ((sh_flags &~ (SHF_MIPS_GPREL |
                        SHF_MIPS_MERGE |
                        SHF_MIPS_ADDR |
-                       SHF_MIPS_STRINGS)) == 0);
+                       SHF_MIPS_STRINGS |
+                       SHF_MIPS_NOSTRIP |
+                       SHF_MIPS_LOCAL |
+                       SHF_MIPS_NAMES |
+                       SHF_MIPS_NODUPE)) == 0);
 }

>
>> diff --git a/src/elflint.c b/src/elflint.c
>> index dd42dcb4..04f1ee92 100644
>> --- a/src/elflint.c
>> +++ b/src/elflint.c
>> @@ -935,7 +935,10 @@ section [%2d] '%s': symbol %zu (%s): non-local symbol outside range described in
>>  	}
>>  
>>        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_LINK") != 0
>> +	  && strcmp (name, "_DYNAMIC_LINKING") != 0)
> Could you add a comment here about both symbols not being local on
> MIPS?

    raw code:

    huangying@Sleepygon:~/elf/elfutils_4$ src/elflint --gnu src/nm
    section [ 7] '.dynsym': symbol 166 (_DYNAMIC_LINKING): non-local section symbol
    section [38] '.symtab': symbol 1052 (_DYNAMIC_LINKING): non-local section symbol
   

>
>>  	ERROR (_("\
>>  section [%2d] '%s': symbol %zu (%s): non-local section symbol\n"),
>>  	       idx, section_name (ebl, idx), cnt, name);
>> @@ -3789,6 +3792,12 @@ cannot get section header for section [%2zu] '%s': %s\n"),
>>  		    && 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;
>> +		  }
> OK. You don't need explicit brackets here
    OK
>
>>  		/* 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
>> @@ -3953,8 +3962,16 @@ section [%2zu] '%s': size not multiple of entry size\n"),
>>  	      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 (ehdr->e_machine == EM_MIPS)
>> +	        {
>> +	          if(sh_flags == SHF_MIPS_NOSTRIP || sh_flags == SHF_MIPS_LOCAL
>> +		   || sh_flags == SHF_MIPS_NAMES || sh_flags == SHF_MIPS_NODUPE)
>> +	            sh_flags &= ~shdr->sh_flags;
>> +	        }
>> +	    }
>>  	  if (sh_flags != 0)
>>  	    ERROR (_("section [%2zu] '%s' contains unknown flag(s)"
>>  			    " %#" PRIx64 "\n"),
> Can this be checked with the machine_section_flag_check hook?
>
> Thanks,
>
> Mark

    OK, add it:

diff --git a/src/elflint.c b/src/elflint.c
index 04f1ee92..56244051 100644
--- a/src/elflint.c
+++ b/src/elflint.c
@@ -3965,12 +3965,13 @@ section [%2zu] '%s': size not multiple of entry size\n"),
            {
              if (gnuld)
                sh_flags &= ~(GElf_Xword) SHF_GNU_RETAIN;
-             if (ehdr->e_machine == EM_MIPS)
-               {
-                 if(sh_flags == SHF_MIPS_NOSTRIP || sh_flags == SHF_MIPS_LOCAL
-                  || sh_flags == SHF_MIPS_NAMES || sh_flags == SHF_MIPS_NODUPE)
-                   sh_flags &= ~shdr->sh_flags;
-               }
+             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;

Thanks,

Ying

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 4/5] stack: Fix stack unwind failure on mips
  2023-05-11 16:07   ` Mark Wielaard
@ 2023-05-18  6:14     ` Ying Huang
  0 siblings, 0 replies; 30+ messages in thread
From: Ying Huang @ 2023-05-18  6:14 UTC (permalink / raw)
  To: Mark Wielaard, elfutils-devel; +Cc: yunqiang.su

[-- Attachment #1: Type: text/plain, Size: 5699 bytes --]

Hi,

在 2023/5/12 00:07, Mark Wielaard 写道:
>>  libebl_backends_a_SOURCES = $(i386_SRCS) $(sh_SRCS) $(x86_64_SRCS) \
>>  			    $(ia64_SRCS) $(alpha_SRCS) $(arm_SRCS) \
>> diff --git a/backends/mips_cfi.c b/backends/mips_cfi.c
>> new file mode 100644
>> index 00000000..77132cc1
>> --- /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) 2023 CIP United Inc.
>> +   This file is part of elfutils.
>> +
>> +   This file is free software; you can redistribute it and/or modify
>> +   it under the terms of either
>> +
>> +     * the GNU Lesser General Public License as published by the Free
>> +       Software Foundation; either version 3 of the License, or (at
>> +       your option) any later version
>> +
>> +   or
>> +
>> +     * the GNU General Public License as published by the Free
>> +       Software Foundation; either version 2 of the License, or (at
>> +       your option) any later version
>> +
>> +   or both in parallel, as here.
>> +
>> +   elfutils is distributed in the hope that it will be useful, but
>> +   WITHOUT ANY WARRANTY; without even the implied warranty of
>> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>> +   General Public License for more details.
>> +
>> +   You should have received copies of the GNU General Public License and
>> +   the GNU Lesser General Public License along with this program.  If
>> +   not, see <http://www.gnu.org/licenses/>.  */
>> +
>> +#ifdef HAVE_CONFIG_H
>> +# include <config.h>
>> +#endif
>> +
>> +#include <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 = -4;
>> +
>> +  abi_info->return_address_register = 31; /* %ra */
>> +
>> +  return 0;
>> +}
> Looks good, but do you have a reference to the ABI docs would be nice
> to add an URL as comment for people to double check.

    document:

    https://irix7.com/techpubs/007-2816-004.pdf

    Page17 Page18 Page14

>> diff --git a/backends/mips_initreg.c b/backends/mips_initreg.c
>> new file mode 100644
>> index 00000000..31b8de13
>> --- /dev/null
>> +++ b/backends/mips_initreg.c
>> @@ -0,0 +1,70 @@
>> +/* Fetch live process registers from TID.
>> +   Copyright (C) 2023 CIP United Inc.
>> +   This file is part of elfutils.
>> +
>> +   This file is free software; you can redistribute it and/or modify
>> +   it under the terms of either
>> +
>> +     * the GNU Lesser General Public License as published by the Free
>> +       Software Foundation; either version 3 of the License, or (at
>> +       your option) any later version
>> +
>> +   or
>> +
>> +     * the GNU General Public License as published by the Free
>> +       Software Foundation; either version 2 of the License, or (at
>> +       your option) any later version
>> +
>> +   or both in parallel, as here.
>> +
>> +   elfutils is distributed in the hope that it will be useful, but
>> +   WITHOUT ANY WARRANTY; without even the implied warranty of
>> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>> +   General Public License for more details.
>> +
>> +   You should have received copies of the GNU General Public License and
>> +   the GNU Lesser General Public License along with this program.  If
>> +   not, see <http://www.gnu.org/licenses/>.  */
>> +
>> +#ifdef HAVE_CONFIG_H
>> +# include <config.h>
>> +#endif
>> +
>> +#include <stdlib.h>
>> +#if (defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__)) && defined(__linux__)
>> +# include <sys/user.h>
>> +# include <sys/ptrace.h>
>> +#endif
>> +
>> +#define BACKEND mips_
>> +#include "libebl_CPU.h"
>> +#include <stdio.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 {
>> +    uint64_t regs[32];
>> +    uint64_t lo;
>> +    uint64_t hi;
>> +    uint64_t pc;
>> +    uint64_t badvaddr;
>> +    uint64_t cause;
>> +    uint64_t status;
>> +};
> Isn't this defined in some standard (or glibc/linux specific) header?

    OK, I would add +#include <asm/ptrace.h>


    Thanks,

    Ying

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 5/5] backends: Fix run-native-test.sh and run-funcretval++11.sh run fail on mips
  2023-05-11 16:38   ` Mark Wielaard
@ 2023-05-18  9:06     ` Ying Huang
  0 siblings, 0 replies; 30+ messages in thread
From: Ying Huang @ 2023-05-18  9:06 UTC (permalink / raw)
  To: Mark Wielaard, elfutils-devel; +Cc: yunqiang.su

[-- Attachment #1: Type: text/plain, Size: 10441 bytes --]

Hi,

在 2023/5/12 00:38, Mark Wielaard 写道:
>> diff --git a/backends/mips_regs.c b/backends/mips_regs.c
>>
>> +
>> +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 66;
>> +
>> +  if (regno < 0 || regno > 65 || namelen < 4)
>> +    return -1;
>> +
>> +  *prefix = "$";
>> +  
>> +  if (regno < 32)
>> +    {
>> +      *setname = "integer";
>> +      *type = DW_ATE_signed;
>> +      *bits = 32;
>> +      if (regno < 32 + 10)
>> +      {
>> +        name[0] = regno + '0';
>> +	namelen = 1;
>> +      }
>> +      else
>> +      {
>> +        name[0] = (regno / 10) + '0';
>> +	name[1] = (regno % 10) + '0';
>> +	namelen = 2;
>> +      }
>> +    }
>> +  else if (regno < 64)
>> +    {
>> +      *setname = "FPU";
>> +      *type = DW_ATE_float;
>> +      *bits = 32;
>> +      name[0] = 'f';
>> +      if (regno < 32 + 10)
>> +      {
>> +        name[1] = (regno - 32) + '0';
>> +	namelen = 2;
>> +      }
>> +      else
>> +      {
>> +        name[1] = (regno - 32) / 10 + '0';
>> +	name[2] = (regno - 32) % 10 + '0';
>> +	namelen = 3;
>> +      }
>>
> OK, but indentation seems slightly off. space vs tabs?


    Yes, those lines that not aligned are tabs, I would fix it. Thanks.


>
>> diff --git a/backends/mips_retval.c b/backends/mips_retval.c
>> new file mode 100644
>> index 00000000..fd9aaefa
>> --- /dev/null
>> +++ b/backends/mips_retval.c
>> @@ -0,0 +1,261 @@
>> +/* Function return value location for Linux/mips ABI.
>> +   Copyright (C) 2005 Red Hat, Inc.
>> +   Copyright (C) 2023 CIP United Inc.
>> +   This file is part of elfutils.
>> +
>> +   This file is free software; you can redistribute it and/or modify
>> +   it under the terms of either
>> +
>> +     * the GNU Lesser General Public License as published by the Free
>> +       Software Foundation; either version 3 of the License, or (at
>> +       your option) any later version
>> +
>> +   or
>> +
>> +     * the GNU General Public License as published by the Free
>> +       Software Foundation; either version 2 of the License, or (at
>> +       your option) any later version
>> +
>> +   or both in parallel, as here.
>> +
>> +   elfutils is distributed in the hope that it will be useful, but
>> +   WITHOUT ANY WARRANTY; without even the implied warranty of
>> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>> +   General Public License for more details.
>> +
>> +   You should have received copies of the GNU General Public License and
>> +   the GNU Lesser General Public License along with this program.  If
>> +   not, see <http://www.gnu.org/licenses/>.  */
>> +
>> +#ifdef HAVE_CONFIG_H
>> +# include <config.h>
>> +#endif
>> +
>> +#include <assert.h>
>> +#include <dwarf.h>
>> +#include <string.h>
>> +#include <elf.h>
>> +#include <stdio.h>
>> +
>> +#define BACKEND mips_
>> +#include "libebl_CPU.h"
>> +#include "libdwP.h"
>> +
>> +/* All the possible MIPS ARCHs. */
>> +enum mips_arch
>> +  {
>> +    MIPS_ARCH_UNKNOWN = 0,
>> +    MIPS_ARCH_32,
>> +    MIPS_ARCH_64,
>> +    MIPS_ARCH_LAST
>> +  };
>> +
>> +/* Find the mips ARCH of the current file */
>> +enum mips_arch find_mips_arch(Elf *elf)
>> +{
>> +  GElf_Ehdr ehdr_mem;
>> +  GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem);
>> +
>> +  if (ehdr == NULL)
>> +    return MIPS_ARCH_LAST;
>> +
>> +  GElf_Word elf_flags = ehdr->e_flags;
>> +
>> +  /* Check elf_flags to see if it specifies the ARCH being used.  */
>> +  switch ((elf_flags & EF_MIPS_ARCH))
>> +    {
>> +    case E_MIPS_ARCH_32:
>> +    case EF_MIPS_ARCH_32R2:
>> +    case E_MIPS_ARCH_32R6:
>> +      return MIPS_ARCH_32;
>> +    case E_MIPS_ARCH_64:
>> +    case EF_MIPS_ARCH_64R2:
>> +    case E_MIPS_ARCH_64R6:
>> +      return MIPS_ARCH_64;
>> +    default:
>> +      return MIPS_ARCH_32;
>> +    }
>> +
>> +  return MIPS_ARCH_UNKNOWN;
>> +}
>>
>> +unsigned int
>> +mips_arch_regsize (enum mips_arch arch)
>> +{
>> +  switch (arch)
>> +    {
>> +    case MIPS_ARCH_32:
>> +      return 4;
>> +    case MIPS_ARCH_64:
>> +      return 8;
>> +    case MIPS_ARCH_UNKNOWN:
>> +    case MIPS_ARCH_LAST:
>> +    default:
>> +      return 0;
>> +    }
>> +}
> So this is different from checking ELFCLASS32/64?

    OK, I would change to use ELFCLASS32/64:

>
>> +/* $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)
>> +{
>> +  /* First find the ARCH used by the elf object */
>> +  enum mips_arch arch = find_mips_arch(functypedie->cu->dbg->elf);
>> +  /* Something went seriously wrong while trying to figure out the ARCH */
>> +  if (arch == MIPS_ARCH_LAST)
>> +    return -1;
>> +
>> +  /* We couldn't identify the ARCH, but the file seems valid */
>> +  if (arch == MIPS_ARCH_UNKNOWN)
>> +    return -3;
>> +
>> +  unsigned int regsize = mips_arch_regsize (arch);
>> +  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 && arch == MIPS_ARCH_32)
>> +                  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:
>> +      /* XXX TODO: Can't handle structure return with other ABI's yet :-/ */
>> +      if ((arch != MIPS_ARCH_32) && (arch != MIPS_ARCH_64))
>> +        return -2;
>> +
>> +      *locp = loc_aggregate;
>> +      return nloc_aggregate;
>> +    }
>> +
>> +  /* 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;
>> +}
> OK. This looks plausible. Would be good to have a reference to the
> actual calling convention.
>
> Thanks,
>
> Mark


Thanks,

YIng

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 1/5] strip: Adapt src/strip -o -f on mips
  2023-05-16  6:38     ` Ying Huang
@ 2023-05-21 21:13       ` Mark Wielaard
  2023-05-24  6:21         ` Ying Huang
  0 siblings, 1 reply; 30+ messages in thread
From: Mark Wielaard @ 2023-05-21 21:13 UTC (permalink / raw)
  To: Ying Huang; +Cc: elfutils-devel, yunqiang.su

Hi Ying,

On Tue, May 16, 2023 at 02:38:45PM +0800, Ying Huang wrote:
> 在 2023/5/9 23:15, Mark Wielaard 写道:
> > On Tue, 2023-04-11 at 16:12 +0800, Ying Huang wrote:
> >> 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.
> > Is there a spec that describes this?
>    
> 
>  references:
> 
>     https://www.linux-mips.org/pub/linux/mips/doc/ABI/elf64-2.4.pdf
> 
>     Page40 && Page41

Thanks. Interesting. If possible please include this URL in a comment.

> > I see you adjusted elf.h to include:
> >
> > +#define ELF64_MIPS_R_TYPE(i)		((i) & 0xff)
> > +#define ELF64_MIPS_R_TYPE2(i)           (((i) >> 8) & 0xff)
> > +#define ELF64_MIPS_R_TYPE3(i)           (((i) >> 16) & 0xff)
> >
> > And various new relocation types for MIPS variants.
> > Our elf.h comes from the glibc project. Have you also submitted these
> > changes to libc-alpha@sourceware.org ?
>     Has submitted.
> 
>     https://sourceware.org/pipermail/libc-alpha/2023-May/148026.html
> 
>     https://sourceware.org/pipermail/libc-alpha/2023-May/148112.html

Thanks. We'll sync them as soon as v3 lands.

>     Has tested on big/little endian machine with big/little endian
> ELF file, all were OK.

Could you post those ELF files somewhere?
Maybe we can add some as test files?

> > It feels like this is in the wrong place and doesn't take into account
> > whether the program itself is running on a big or little endian
> > machine.
> >
> > Maybe I am misunderstanding why this conversion is needed always. But I
> > would have expected a specific conversion function for MIPS for
> > ELF_T_REL and/or ELF_T_RELA (which are currently generic).
>
>     1.Considering that some people directly use the original data instead of the interface function gelf_getrela;
> 
>     2.Because there is only one parameter, so can not modify the macro ELF64_R_TYPE;
> 
>     3.If the mips interface function is added, other packages using libelf will not be compatible with mips, and the place where gelf_getrela is used need be modified.
> 
>     Where do you think is the most suitable place to do mips conversion?

So for the convert_data case in elf_getdata.c I would expect a special
conversion function being defined for ELF_T_REL and ELF_T_RELA. This
normally comes from __elf_xfctstom. I realize now that cannot easily
take an Elf of machine type. But I would expect to have the conversion
be done by a new function that can be assigned to fp in convert_data:

      /* Get the conversion function.  */
      fp = __elf_xfctstom[eclass - 1][type];

I still don't fully understand the need of the code in elf_update. I
assume that is needed in case the file was used with ELF_C_RDWR_MMAP?

Cheers,

Mark

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 1/5] strip: Adapt src/strip -o -f on mips
  2023-05-16  7:34       ` Ying Huang
@ 2023-05-21 21:14         ` Mark Wielaard
  2023-05-26  2:48           ` Ying Huang
  0 siblings, 1 reply; 30+ messages in thread
From: Mark Wielaard @ 2023-05-21 21:14 UTC (permalink / raw)
  To: Ying Huang; +Cc: elfutils-devel

Hi Ying,

On Tue, May 16, 2023 at 03:34:01PM +0800, Ying Huang wrote:
> 在 2023/5/16 14:46, Ying Huang 写道:
> > >> 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.
> > > Where do these segfaults show up?
> >     The screenshot of the segment error was not uploaded successfully in the last email, upload again.

Sorry, the mailinglist seems to strip the image attachements.

> huangying@Sleepygon:~/elf/elfutils_4$ src/elflint src/nm.o
> Segmentation fault
> huangying@Sleepygon:~/elf/elfutils_4$ src/elflint src/strip.o
> Segmentation fault

When running under gdb, what is the backtrace of the crash?

Thanks,

Mark

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 1/5] strip: Adapt src/strip -o -f on mips
  2023-05-21 21:13       ` Mark Wielaard
@ 2023-05-24  6:21         ` Ying Huang
  0 siblings, 0 replies; 30+ messages in thread
From: Ying Huang @ 2023-05-24  6:21 UTC (permalink / raw)
  To: Mark Wielaard; +Cc: elfutils-devel, yunqiang.su

[-- Attachment #1: Type: text/plain, Size: 6431 bytes --]

在 2023/5/22 05:13, Mark Wielaard 写道:
> Hi Ying,
>
> On Tue, May 16, 2023 at 02:38:45PM +0800, Ying Huang wrote:
>> 在 2023/5/9 23:15, Mark Wielaard 写道:
>>> On Tue, 2023-04-11 at 16:12 +0800, Ying Huang wrote:
>>>> 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.
>>> Is there a spec that describes this?
>>    
>>
>>  references:
>>
>>     https://www.linux-mips.org/pub/linux/mips/doc/ABI/elf64-2.4.pdf
>>
>>     Page40 && Page41
> Thanks. Interesting. If possible please include this URL in a comment.
    OK.
>
>>> I see you adjusted elf.h to include:
>>>
>>> +#define ELF64_MIPS_R_TYPE(i)		((i) & 0xff)
>>> +#define ELF64_MIPS_R_TYPE2(i)           (((i) >> 8) & 0xff)
>>> +#define ELF64_MIPS_R_TYPE3(i)           (((i) >> 16) & 0xff)
>>>
>>> And various new relocation types for MIPS variants.
>>> Our elf.h comes from the glibc project. Have you also submitted these
>>> changes to libc-alpha@sourceware.org ?
>>     Has submitted.
>>
>>     https://sourceware.org/pipermail/libc-alpha/2023-May/148026.html
>>
>>     https://sourceware.org/pipermail/libc-alpha/2023-May/148112.html
> Thanks. We'll sync them as soon as v3 lands.
>
>>     Has tested on big/little endian machine with big/little endian
>> ELF file, all were OK.
> Could you post those ELF files somewhere?
> Maybe we can add some as test files?
    The ELF files I used were "src/strip.o" which were generated on big/little endian machine.

root@debian-sid-mipsbe:~# readelf -h strip.o
ELF Header:
  Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
  Class:                             ELF64
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              REL (Relocatable file)
  Machine:                           MIPS R3000
  Version:                           0x1
  Entry point address:               0x0
  Start of program headers:          0 (bytes into file)
  Start of section headers:          426696 (bytes into file)
  Flags:                             0x80000007, noreorder, pic, cpic, mips64r2
  Size of this header:               64 (bytes)
  Size of program headers:           0 (bytes)
  Number of program headers:         0
  Size of section headers:           64 (bytes)
  Number of section headers:         41
  Section header string table index: 40
root@debian-sid-mipsbe:~# readelf -h elfutils_debug/src/strip.o
ELF Header:
  Magic:   7f 45 4c 46 01 02 01 00 00 00 00 00 00 00 00 00
  Class:                             ELF32
  Data:                              2's complement, big endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              REL (Relocatable file)
  Machine:                           MIPS R3000
  Version:                           0x1
  Entry point address:               0x0
  Start of program headers:          0 (bytes into file)
  Start of section headers:          215248 (bytes into file)
  Flags:                             0x70001007, noreorder, pic, cpic, o32, mips32r2
  Size of this header:               52 (bytes)
  Size of program headers:           0 (bytes)
  Number of program headers:         0
  Size of section headers:           40 (bytes)
  Number of section headers:         40
  Section header string table index: 39
root@debian-sid-mipsbe:~#

>>> It feels like this is in the wrong place and doesn't take into account
>>> whether the program itself is running on a big or little endian
>>> machine.
>>>
>>> Maybe I am misunderstanding why this conversion is needed always. But I
>>> would have expected a specific conversion function for MIPS for
>>> ELF_T_REL and/or ELF_T_RELA (which are currently generic).
>>     1.Considering that some people directly use the original data instead of the interface function gelf_getrela;
>>
>>     2.Because there is only one parameter, so can not modify the macro ELF64_R_TYPE;
>>
>>     3.If the mips interface function is added, other packages using libelf will not be compatible with mips, and the place where gelf_getrela is used need be modified.
>>
>>     Where do you think is the most suitable place to do mips conversion?
> So for the convert_data case in elf_getdata.c I would expect a special
> conversion function being defined for ELF_T_REL and ELF_T_RELA. This
> normally comes from __elf_xfctstom. I realize now that cannot easily
> take an Elf of machine type. But I would expect to have the conversion
> be done by a new function that can be assigned to fp in convert_data:
>
>       /* Get the conversion function.  */
>       fp = __elf_xfctstom[eclass - 1][type];
        Maybe I can create a new function named "convert_data_for_mips" and contained the code that added in convert_data?
>
> I still don't fully understand the need of the code in elf_update. I
> assume that is needed in case the file was used with ELF_C_RDWR_MMAP?
>
> Cheers,
>
> Mark

    Because we convert the relocation data for mips64el in elf_getdata.c, eg src/strip, and when we write elf  to file, need confirm the relocation data is in original order bits.

    When file use ELF_C_RDWR_MMAP, only impact whether malloc data_base in convert_data.


    Thanks,

    Ying

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 1/5] strip: Adapt src/strip -o -f on mips
  2023-05-21 21:14         ` Mark Wielaard
@ 2023-05-26  2:48           ` Ying Huang
  0 siblings, 0 replies; 30+ messages in thread
From: Ying Huang @ 2023-05-26  2:48 UTC (permalink / raw)
  To: Mark Wielaard; +Cc: elfutils-devel, yunqiang.su

[-- Attachment #1: Type: text/plain, Size: 3489 bytes --]

Hi Mark,

在 2023/5/22 05:14, Mark Wielaard 写道:
> Hi Ying,
>
> On Tue, May 16, 2023 at 03:34:01PM +0800, Ying Huang wrote:
>> 在 2023/5/16 14:46, Ying Huang 写道:
>>>>> 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.
>>>> Where do these segfaults show up?
>>>     The screenshot of the segment error was not uploaded successfully in the last email, upload again.
> Sorry, the mailinglist seems to strip the image attachements.
>
>> huangying@Sleepygon:~/elf/elfutils_4$ src/elflint src/nm.o
>> Segmentation fault
>> huangying@Sleepygon:~/elf/elfutils_4$ src/elflint src/strip.o
>> Segmentation fault
> When running under gdb, what is the backtrace of the crash?
>
> Thanks,
>
> Mark

huangying@Sleepygon:~/elf/elfutils_4$ src/elflint src/nm.o

Segmentation fault (core dumped)

huangying@Sleepygon:~/elf/elfutils_4$ gdb src/elflint

...

(gdb) bt
#0  convert_data (type=ELF_T_RELA, size=24912, data=1, eclass=<optimized out>, scn=0xaad3698f98) at elf_getdata.c:254
#1  __libelf_set_data_list_rdlock (scn=0xaad3698f98, wrlocked=<optimized out>) at elf_getdata.c:515
#2  0x000000fff3862f14 in __elf_getdata_rdlock (scn=0xaad3698f98, data=<optimized out>) at elf_getdata.c:622
#3  0x000000fff3862f54 in elf_getdata (scn=<optimized out>, data=<optimized out>) at elf_getdata.c:640
#4  0x000000aaac571c9c in check_rela (ebl=0xaad369b120, ehdr=0xfffb9451b0, shdr=0xfffb945008, idx=<optimized out>) at elflint.c:1500
#5  0x000000aaac574e40 in check_sections (ebl=0xaad369b120, ehdr=0xfffb9451b0) at elflint.c:4198
#6  0x000000aaac5784ac in process_elf_file (only_one=<optimized out>, size=<optimized out>, fname=<optimized out>, suffix=<optimized out>, prefix=<optimized out>, elf=<optimized out>) at elflint.c:4842
#7  process_file (fd=<optimized out>, elf=<optimized out>, prefix=<optimized out>, suffix=<optimized out>, fname=<optimized out>, size=<optimized out>, only_one=<optimized out>) at elflint.c:241
#8  0x000000aaac5688fc in main (argc=<optimized out>, argv=0xfffb9455d8) at elflint.c:174

...


    If I did not malloc to scn->data_base, would occur Segment fault when we want to operate this space "&scn->data_list.data.d". Because src/elflint use read-mmap method to map file.

    Show 10 lines of code "libelf/elf_getdata.c" starting at line 254:

huangying@Sleepygon:~/elf/elfutils_4$ cat libelf/elf_getdata.c | tail -n +254 | head -n 10
            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));


    Show elflint map method in src/elflint.c:

    /* Create an `Elf' descriptor. */

    Elf *elf = elf_begin (fd, ELF_C_READ_MMAP, NULL);


Thanks,

Ying

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 2/5] readelf: Adapt src/readelf -h/-S/-r/-w/-l/-d/-a on mips
  2023-05-11 14:31   ` Mark Wielaard
  2023-05-16  8:01     ` Ying Huang
@ 2023-07-24  8:35     ` Ying Huang
  2023-07-25  8:15       ` Ying Huang
  2023-08-01  9:25       ` Mark Wielaard
  1 sibling, 2 replies; 30+ messages in thread
From: Ying Huang @ 2023-07-24  8:35 UTC (permalink / raw)
  To: Mark Wielaard; +Cc: elfutils-devel, yunqiang.su

[-- Attachment #1: Type: text/plain, Size: 1990 bytes --]

Hi Mark,

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

Thanks,

Ying

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 2/5] readelf: Adapt src/readelf -h/-S/-r/-w/-l/-d/-a on mips
  2023-07-24  8:35     ` Ying Huang
@ 2023-07-25  8:15       ` Ying Huang
  2023-07-27  6:08         ` Ying Huang
  2023-08-01 13:14         ` Mark Wielaard
  2023-08-01  9:25       ` Mark Wielaard
  1 sibling, 2 replies; 30+ messages in thread
From: Ying Huang @ 2023-07-25  8:15 UTC (permalink / raw)
  To: Mark Wielaard; +Cc: elfutils-devel, yunqiang.su

[-- Attachment #1: Type: text/plain, Size: 2773 bytes --]

Hi Mark,

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

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

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

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

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

Thanks,

Ying

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

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 2/5] readelf: Adapt src/readelf -h/-S/-r/-w/-l/-d/-a on mips
  2023-07-25  8:15       ` Ying Huang
@ 2023-07-27  6:08         ` Ying Huang
  2023-08-01 21:43           ` Mark Wielaard
  2023-08-01 13:14         ` Mark Wielaard
  1 sibling, 1 reply; 30+ messages in thread
From: Ying Huang @ 2023-07-27  6:08 UTC (permalink / raw)
  To: Mark Wielaard; +Cc: elfutils-devel, yunqiang.su

[-- Attachment #1: Type: text/plain, Size: 3205 bytes --]

Hi Mark,

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

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

Thanks,

Ying

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

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 2/5] readelf: Adapt src/readelf -h/-S/-r/-w/-l/-d/-a on mips
  2023-07-24  8:35     ` Ying Huang
  2023-07-25  8:15       ` Ying Huang
@ 2023-08-01  9:25       ` Mark Wielaard
  1 sibling, 0 replies; 30+ messages in thread
From: Mark Wielaard @ 2023-08-01  9:25 UTC (permalink / raw)
  To: Ying Huang; +Cc: elfutils-devel, yunqiang.su

Hi Ying,

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

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

Cheers,

Mark

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 2/5] readelf: Adapt src/readelf -h/-S/-r/-w/-l/-d/-a on mips
  2023-07-25  8:15       ` Ying Huang
  2023-07-27  6:08         ` Ying Huang
@ 2023-08-01 13:14         ` Mark Wielaard
  1 sibling, 0 replies; 30+ messages in thread
From: Mark Wielaard @ 2023-08-01 13:14 UTC (permalink / raw)
  To: Ying Huang; +Cc: elfutils-devel, yunqiang.su

Hi Ying,

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

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

Cheers,

Mark

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 2/5] readelf: Adapt src/readelf -h/-S/-r/-w/-l/-d/-a on mips
  2023-07-27  6:08         ` Ying Huang
@ 2023-08-01 21:43           ` Mark Wielaard
  0 siblings, 0 replies; 30+ messages in thread
From: Mark Wielaard @ 2023-08-01 21:43 UTC (permalink / raw)
  To: Ying Huang; +Cc: elfutils-devel, yunqiang.su

Hi Ying,

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

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

Is there a specific mips elf specification we are following?

Cheers,

Mark

^ permalink raw reply	[flat|nested] 30+ messages in thread

end of thread, other threads:[~2023-08-01 21:43 UTC | newest]

Thread overview: 30+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-04-11  8:12 [PATCH 0/5] Add support for MIPS Ying Huang
2023-04-11  8:12 ` [PATCH 1/5] strip: Adapt src/strip -o -f on mips Ying Huang
2023-05-09 15:15   ` Mark Wielaard
2023-05-16  6:38     ` Ying Huang
2023-05-21 21:13       ` Mark Wielaard
2023-05-24  6:21         ` Ying Huang
2023-05-16  6:46     ` Ying Huang
2023-05-16  7:34       ` Ying Huang
2023-05-21 21:14         ` Mark Wielaard
2023-05-26  2:48           ` Ying Huang
2023-05-16  8:05     ` [EXTERNAL] " Luke Diamand
2023-04-11  8:12 ` [PATCH 2/5] readelf: Adapt src/readelf -h/-S/-r/-w/-l/-d/-a " Ying Huang
2023-05-11 14:31   ` Mark Wielaard
2023-05-16  8:01     ` Ying Huang
2023-07-24  8:35     ` Ying Huang
2023-07-25  8:15       ` Ying Huang
2023-07-27  6:08         ` Ying Huang
2023-08-01 21:43           ` Mark Wielaard
2023-08-01 13:14         ` Mark Wielaard
2023-08-01  9:25       ` Mark Wielaard
2023-04-11  8:12 ` [PATCH 3/5] elflint: Fix invalid type of relocation info and other issues " Ying Huang
2023-05-11 15:59   ` Mark Wielaard
2023-05-17  9:14     ` Ying Huang
2023-04-11  8:12 ` [PATCH 4/5] stack: Fix stack unwind failure " Ying Huang
2023-05-11 16:07   ` Mark Wielaard
2023-05-18  6:14     ` Ying Huang
2023-04-11  8:12 ` [PATCH 5/5] backends: Fix run-native-test.sh and run-funcretval++11.sh run fail " Ying Huang
2023-05-11 16:38   ` Mark Wielaard
2023-05-18  9:06     ` Ying Huang
2023-05-04  2:24 ` [PATCH 0/5] Add support for MIPS 黄莺

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).