public inbox for elfutils@sourceware.org
 help / color / mirror / Atom feed
From: "Ying Huang" <ying.huang@oss.cipunited.com>
To: <elfutils-devel@sourceware.org>
Cc: "Ying Huang" <ying.huang@oss.cipunited.com>
Subject: [PATCH 1/5] strip: Adapt src/strip -o -f on mips
Date: Tue, 11 Apr 2023 16:12:40 +0800	[thread overview]
Message-ID: <20230411081141.1762395-2-ying.huang@oss.cipunited.com> (raw)
In-Reply-To: <20230411081141.1762395-1-ying.huang@oss.cipunited.com>

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

  reply	other threads:[~2023-04-11  8:12 UTC|newest]

Thread overview: 30+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-04-11  8:12 [PATCH 0/5] Add support for MIPS Ying Huang
2023-04-11  8:12 ` Ying Huang [this message]
2023-05-09 15:15   ` [PATCH 1/5] strip: Adapt src/strip -o -f on mips 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 黄莺

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20230411081141.1762395-2-ying.huang@oss.cipunited.com \
    --to=ying.huang@oss.cipunited.com \
    --cc=elfutils-devel@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).