[v3,1/6] Support Mips architecture

Message ID 20240305095122.889077-2-ying.huang@oss.cipunited.com
State Committed
Headers
Series Add support for MIPS |

Commit Message

Ying Huang March 5, 2024, 9:51 a.m. UTC
  From: Ying Huang <ying.huang@oss.cipunited.com>

Signed-off-by: Ying Huang <ying.huang@oss.cipunited.com>
---
 backends/Makefile.am    |   6 +-
 backends/mips_init.c    |  52 ++++
 backends/mips_reloc.def |  93 +++++++
 backends/mips_symbol.c  |  63 +++++
 libebl/eblopenbackend.c |   2 +
 libelf/libelfP.h        |   3 +
 tests/libelf.h          | 541 ++++++++++++++++++++++++++++++++++++++++
 7 files changed, 758 insertions(+), 2 deletions(-)
 create mode 100644 backends/mips_init.c
 create mode 100644 backends/mips_reloc.def
 create mode 100644 backends/mips_symbol.c
 create mode 100644 tests/libelf.h
  

Comments

Ying Huang March 11, 2024, 10:02 a.m. UTC | #1
Hi Mark,

Could you please review these patches, I have splited patch v2 1/5 to patch v3 1/6 and 2/6.

Thanks,

Ying


在 2024/3/5 17:51, Ying Huang 写道:
> From: Ying Huang <ying.huang@oss.cipunited.com>
>
> Signed-off-by: Ying Huang <ying.huang@oss.cipunited.com>
> ---
>  backends/Makefile.am    |   6 +-
>  backends/mips_init.c    |  52 ++++
>  backends/mips_reloc.def |  93 +++++++
>  backends/mips_symbol.c  |  63 +++++
>  libebl/eblopenbackend.c |   2 +
>  libelf/libelfP.h        |   3 +
>  tests/libelf.h          | 541 ++++++++++++++++++++++++++++++++++++++++
>  7 files changed, 758 insertions(+), 2 deletions(-)
>  create mode 100644 backends/mips_init.c
>  create mode 100644 backends/mips_reloc.def
>  create mode 100644 backends/mips_symbol.c
>  create mode 100644 tests/libelf.h
>
> diff --git a/backends/Makefile.am b/backends/Makefile.am
> index bbb2aac7..b946fd30 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 \
> @@ -102,12 +102,14 @@ loongarch_SRCS = loongarch_init.c loongarch_symbol.c loongarch_cfi.c \
>  
>  arc_SRCS = arc_init.c arc_symbol.c
>  
> +mips_SRCS = mips_init.c mips_symbol.c
> +
>  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..cedd08ca
> --- /dev/null
> +++ b/backends/mips_init.c
> @@ -0,0 +1,52 @@
> +/* Initialization of MIPS specific backend library.
> +   Copyright (C) 2024 CIP United Inc.
> +   This file is part of elfutils.
> +
> +   This file is free software; you can redistribute it and/or modify
> +   it under the terms of either
> +
> +     * the GNU Lesser General Public License as published by the Free
> +       Software Foundation; either version 3 of the License, or (at
> +       your option) any later version
> +
> +   or
> +
> +     * the GNU General Public License as published by the Free
> +       Software Foundation; either version 2 of the License, or (at
> +       your option) any later version
> +
> +   or both in parallel, as here.
> +
> +   elfutils is distributed in the hope that it will be useful, but
> +   WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   General Public License for more details.
> +
> +   You should have received copies of the GNU General Public License and
> +   the GNU Lesser General Public License along with this program.  If
> +   not, see <http://www.gnu.org/licenses/>.  */
> +
> +#ifdef HAVE_CONFIG_H
> +# include <config.h>
> +#endif
> +
> +#define BACKEND		mips_
> +#define RELOC_PREFIX	R_MIPS_
> +#include "libebl_CPU.h"
> +#include "libelfP.h"
> +
> +#define RELOC_TYPE_ID(type) ((type) & 0xff)
> +
> +/* 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..5120980c
> --- /dev/null
> +++ b/backends/mips_reloc.def
> @@ -0,0 +1,93 @@
> +/* List the relocation types for MIPS.  -*- C -*-
> +   Copyright (C) 2024 CIP United Inc.
> +   This file is part of elfutils.
> +
> +   This file is free software; you can redistribute it and/or modify
> +   it under the terms of either
> +
> +     * the GNU Lesser General Public License as published by the Free
> +       Software Foundation; either version 3 of the License, or (at
> +       your option) any later version
> +
> +   or
> +
> +     * the GNU General Public License as published by the Free
> +       Software Foundation; either version 2 of the License, or (at
> +       your option) any later version
> +
> +   or both in parallel, as here.
> +
> +   elfutils is distributed in the hope that it will be useful, but
> +   WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   General Public License for more details.
> +
> +   You should have received copies of the GNU General Public License and
> +   the GNU Lesser General Public License along with this program.  If
> +   not, see <http://www.gnu.org/licenses/>.  */
> +
> +/*	    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..f2a46495
> --- /dev/null
> +++ b/backends/mips_symbol.c
> @@ -0,0 +1,63 @@
> +/* MIPS specific symbolic name handling.
> +   Copyright (C) 2024 CIP United Inc.
> +   This file is part of elfutils.
> +
> +   This file is free software; you can redistribute it and/or modify
> +   it under the terms of either
> +
> +     * the GNU Lesser General Public License as published by the Free
> +       Software Foundation; either version 3 of the License, or (at
> +       your option) any later version
> +
> +   or
> +
> +     * the GNU General Public License as published by the Free
> +       Software Foundation; either version 2 of the License, or (at
> +       your option) any later version
> +
> +   or both in parallel, as here.
> +
> +   elfutils is distributed in the hope that it will be useful, but
> +   WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   General Public License for more details.
> +
> +   You should have received copies of the GNU General Public License and
> +   the GNU Lesser General Public License along with this program.  If
> +   not, see <http://www.gnu.org/licenses/>.  */
> +
> +#ifdef HAVE_CONFIG_H
> +# include <config.h>
> +#endif
> +
> +#include <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_TYPE1(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/libelfP.h b/libelf/libelfP.h
> index ed061abb..bdd2cc6a 100644
> --- a/libelf/libelfP.h
> +++ b/libelf/libelfP.h
> @@ -617,4 +617,7 @@ extern void __libelf_reset_rawdata (Elf_Scn *scn, void *buf, size_t size,
>  #define INVALID_NDX(ndx, type, data) \
>    unlikely ((data)->d_size / sizeof (type) <= (unsigned int) (ndx))
>  
> +#define ELF64_MIPS_R_TYPE1(i)          ((i) & 0xff)
> +#define ELF64_MIPS_R_TYPE2(i)           (((i) >> 8) & 0xff)
> +#define ELF64_MIPS_R_TYPE3(i)           (((i) >> 16) & 0xff)
>  #endif  /* libelfP.h */
> diff --git a/tests/libelf.h b/tests/libelf.h
> new file mode 100644
> index 00000000..d3f057b4
> --- /dev/null
> +++ b/tests/libelf.h
> @@ -0,0 +1,541 @@
> +/* Interface for libelf.
> +   Copyright (C) 1998-2010, 2015 Red Hat, 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/>.  */
> +
> +#ifndef _LIBELF_H
> +#define _LIBELF_H 1
> +
> +#include <stdint.h>
> +#include <sys/types.h>
> +
> +/* Get the ELF types.  */
> +#include <elf.h>
> +
> +#ifndef SHF_COMPRESSED
> + /* Older glibc elf.h might not yet define the ELF compression types.  */
> + #define SHF_COMPRESSED      (1 << 11)  /* Section with compressed data. */
> +
> + /* Section compression header.  Used when SHF_COMPRESSED is set.  */
> +
> + typedef struct
> + {
> +   Elf32_Word   ch_type;        /* Compression format.  */
> +   Elf32_Word   ch_size;        /* Uncompressed data size.  */
> +   Elf32_Word   ch_addralign;   /* Uncompressed data alignment.  */
> + } Elf32_Chdr;
> +
> + typedef struct
> + {
> +   Elf64_Word   ch_type;        /* Compression format.  */
> +   Elf64_Word   ch_reserved;
> +   Elf64_Xword  ch_size;        /* Uncompressed data size.  */
> +   Elf64_Xword  ch_addralign;   /* Uncompressed data alignment.  */
> + } Elf64_Chdr;
> +
> + /* Legal values for ch_type (compression algorithm).  */
> + #define ELFCOMPRESS_ZLIB       1          /* ZLIB/DEFLATE algorithm.  */
> + #define ELFCOMPRESS_LOOS       0x60000000 /* Start of OS-specific.  */
> + #define ELFCOMPRESS_HIOS       0x6fffffff /* End of OS-specific.  */
> + #define ELFCOMPRESS_LOPROC     0x70000000 /* Start of processor-specific.  */
> + #define ELFCOMPRESS_HIPROC     0x7fffffff /* End of processor-specific.  */
> +#endif
> +
> +#ifndef ELFCOMPRESS_ZSTD
> + /* So ZSTD compression can be used even with an old system elf.h.  */
> + #define ELFCOMPRESS_ZSTD       2          /* Zstandard algorithm.  */
> +#endif
> +
> +#ifndef SHT_RELR
> + /* So RELR defines/typedefs can be used even with an old system elf.h.  */
> + #define SHT_RELR       19      /* RELR relative relocations */
> +
> + /* RELR relocation table entry */
> + typedef Elf32_Word     Elf32_Relr;
> + typedef Elf64_Xword    Elf64_Relr;
> +
> + #define DT_RELRSZ      35      /* Total size of RELR relative relocations */
> + #define DT_RELR        36      /* Address of RELR relative relocations */
> + #define DT_RELRENT     37      /* Size of one RELR relative relocaction */
> +#endif
> +
> +#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)
> +# define __nonnull_attribute__(...) __attribute__ ((__nonnull__ (__VA_ARGS__)))
> +# define __deprecated_attribute__ __attribute__ ((__deprecated__))
> +# define __pure_attribute__ __attribute__ ((__pure__))
> +# define __const_attribute__ __attribute__ ((__const__))
> +#else
> +# define __nonnull_attribute__(...)
> +# define __deprecated_attribute__
> +# define __pure_attribute__
> +# define __const_attribute__
> +#endif
> +
> +#if __GNUC__ < 4
> +#define __noreturn_attribute__
> +#else
> +#define __noreturn_attribute__ __attribute__ ((noreturn))
> +#endif
> +
> +#ifdef __GNUC_STDC_INLINE__
> +# define __libdw_extern_inline extern __inline __attribute__ ((__gnu_inline__))
> +#else
> +# define __libdw_extern_inline extern __inline
> +#endif
> +
> +/* Known translation types.  */
> +typedef enum
> +{
> +  ELF_T_BYTE,                   /* unsigned char */
> +  ELF_T_ADDR,                   /* Elf32_Addr, Elf64_Addr, ... */
> +  ELF_T_DYN,                    /* Dynamic section record.  */
> +  ELF_T_EHDR,                   /* ELF header.  */
> +  ELF_T_HALF,                   /* Elf32_Half, Elf64_Half, ... */
> +  ELF_T_OFF,                    /* Elf32_Off, Elf64_Off, ... */
> +  ELF_T_PHDR,                   /* Program header.  */
> +  ELF_T_RELA,                   /* Relocation entry with addend.  */
> +  ELF_T_REL,                    /* Relocation entry.  */
> +  ELF_T_SHDR,                   /* Section header.  */
> +  ELF_T_SWORD,                  /* Elf32_Sword, Elf64_Sword, ... */
> +  ELF_T_SYM,                    /* Symbol record.  */
> +  ELF_T_WORD,                   /* Elf32_Word, Elf64_Word, ... */
> +  ELF_T_XWORD,                  /* Elf32_Xword, Elf64_Xword, ... */
> +  ELF_T_SXWORD,                 /* Elf32_Sxword, Elf64_Sxword, ... */
> +  ELF_T_VDEF,                   /* Elf32_Verdef, Elf64_Verdef, ... */
> +  ELF_T_VDAUX,                  /* Elf32_Verdaux, Elf64_Verdaux, ... */
> +  ELF_T_VNEED,                  /* Elf32_Verneed, Elf64_Verneed, ... */
> +  ELF_T_VNAUX,                  /* Elf32_Vernaux, Elf64_Vernaux, ... */
> +  ELF_T_NHDR,                   /* Elf32_Nhdr, Elf64_Nhdr, ... */
> +  ELF_T_SYMINFO,		/* Elf32_Syminfo, Elf64_Syminfo, ... */
> +  ELF_T_MOVE,			/* Elf32_Move, Elf64_Move, ... */
> +  ELF_T_LIB,			/* Elf32_Lib, Elf64_Lib, ... */
> +  ELF_T_GNUHASH,		/* GNU-style hash section.  */
> +  ELF_T_AUXV,			/* Elf32_auxv_t, Elf64_auxv_t, ... */
> +  ELF_T_CHDR,			/* Compressed, Elf32_Chdr, Elf64_Chdr, ... */
> +  ELF_T_NHDR8,			/* Special GNU Properties note.  Same as Nhdr,
> +				   except padding.  */
> +  ELF_T_RELR,			/* Relative relocation entry.  */
> +  /* Keep this the last entry.  */
> +  ELF_T_NUM
> +} Elf_Type;
> +
> +/* Descriptor for data to be converted to or from memory format.  */
> +typedef struct
> +{
> +  void *d_buf;			/* Pointer to the actual data.  */
> +  Elf_Type d_type;		/* Type of this piece of data.  */
> +  unsigned int d_version;	/* ELF version.  */
> +  size_t d_size;		/* Size in bytes.  */
> +  int64_t d_off;		/* Offset into section.  */
> +  size_t d_align;		/* Alignment in section.  */
> +} Elf_Data;
> +
> +
> +/* Commands for `...'.  */
> +typedef enum
> +{
> +  ELF_C_NULL,			/* Nothing, terminate, or compute only.  */
> +  ELF_C_READ,			/* Read .. */
> +  ELF_C_RDWR,			/* Read and write .. */
> +  ELF_C_WRITE,			/* Write .. */
> +  ELF_C_CLR,			/* Clear flag.  */
> +  ELF_C_SET,			/* Set flag.  */
> +  ELF_C_FDDONE,			/* Signal that file descriptor will not be
> +				   used anymore.  */
> +  ELF_C_FDREAD,			/* Read rest of data so that file descriptor
> +				   is not used anymore.  */
> +  /* The following are extensions.  */
> +  ELF_C_READ_MMAP,		/* Read, but mmap the file if possible.  */
> +  ELF_C_RDWR_MMAP,		/* Read and write, with mmap.  */
> +  ELF_C_WRITE_MMAP,		/* Write, with mmap.  */
> +  ELF_C_READ_MMAP_PRIVATE,	/* Read, but memory is writable, results are
> +				   not written to the file.  */
> +  ELF_C_EMPTY,			/* Copy basic file data but not the content. */
> +  /* Keep this the last entry.  */
> +  ELF_C_NUM
> +} Elf_Cmd;
> +
> +
> +/* Flags for the ELF structures.  */
> +enum
> +{
> +  ELF_F_DIRTY = 0x1,
> +#define ELF_F_DIRTY		ELF_F_DIRTY
> +  ELF_F_LAYOUT = 0x4,
> +#define ELF_F_LAYOUT		ELF_F_LAYOUT
> +  ELF_F_PERMISSIVE = 0x8
> +#define ELF_F_PERMISSIVE	ELF_F_PERMISSIVE
> +};
> +
> +/* Flags for elf_compress[_gnu].  */
> +enum
> +{
> +  ELF_CHF_FORCE = 0x1
> +#define ELF_CHF_FORCE ELF_CHF_FORCE
> +};
> +
> +/* Identification values for recognized object files.  */
> +typedef enum
> +{
> +  ELF_K_NONE,			/* Unknown.  */
> +  ELF_K_AR,			/* Archive.  */
> +  ELF_K_COFF,			/* Stupid old COFF.  */
> +  ELF_K_ELF,			/* ELF file.  */
> +  /* Keep this the last entry.  */
> +  ELF_K_NUM
> +} Elf_Kind;
> +
> +
> +/* Archive member header.  */
> +typedef struct
> +{
> +  char *ar_name;		/* Name of archive member.  */
> +  time_t ar_date;		/* File date.  */
> +  uid_t ar_uid;			/* User ID.  */
> +  gid_t ar_gid;			/* Group ID.  */
> +  mode_t ar_mode;		/* File mode.  */
> +  int64_t ar_size;		/* File size.  */
> +  char *ar_rawname;		/* Original name of archive member.  */
> +} Elf_Arhdr;
> +
> +
> +/* Archive symbol table entry.  */
> +typedef struct
> +{
> +  char *as_name;		/* Symbol name.  */
> +  size_t as_off;		/* Offset for this file in the archive.  */
> +  unsigned long int as_hash;	/* Hash value of the name.  */
> +} Elf_Arsym;
> +
> +
> +/* Descriptor for the ELF file.  */
> +typedef struct Elf Elf;
> +
> +/* Descriptor for ELF file section.  */
> +typedef struct Elf_Scn Elf_Scn;
> +
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif
> +
> +/* Return descriptor for ELF file to work according to CMD.  */
> +extern Elf *elf_begin (int __fildes, Elf_Cmd __cmd, Elf *__ref);
> +
> +/* Create a clone of an existing ELF descriptor.  */
> +  extern Elf *elf_clone (Elf *__elf, Elf_Cmd __cmd);
> +
> +/* Create descriptor for memory region.  */
> +extern Elf *elf_memory (char *__image, size_t __size);
> +
> +/* Advance archive descriptor to next element.  */
> +extern Elf_Cmd elf_next (Elf *__elf);
> +
> +/* Free resources allocated for ELF.  */
> +extern int elf_end (Elf *__elf);
> +
> +/* Update ELF descriptor and write file to disk.  */
> +extern int64_t elf_update (Elf *__elf, Elf_Cmd __cmd);
> +
> +/* Determine what kind of file is associated with ELF.  */
> +extern Elf_Kind elf_kind (Elf *__elf) __pure_attribute__;
> +
> +/* Get the base offset for an object file.  */
> +extern int64_t elf_getbase (Elf *__elf);
> +
> +
> +/* Retrieve file identification data.  */
> +extern char *elf_getident (Elf *__elf, size_t *__nbytes);
> +
> +/* Retrieve class-dependent object file header.  */
> +extern Elf32_Ehdr *elf32_getehdr (Elf *__elf);
> +/* Similar but this time the binary calls is ELFCLASS64.  */
> +extern Elf64_Ehdr *elf64_getehdr (Elf *__elf);
> +
> +/* Create ELF header if none exists.  */
> +extern Elf32_Ehdr *elf32_newehdr (Elf *__elf);
> +/* Similar but this time the binary calls is ELFCLASS64.  */
> +extern Elf64_Ehdr *elf64_newehdr (Elf *__elf);
> +
> +/* Get the number of program headers in the ELF file.  If the file uses
> +   more headers than can be represented in the e_phnum field of the ELF
> +   header the information from the sh_info field in the zeroth section
> +   header is used.  */
> +extern int elf_getphdrnum (Elf *__elf, size_t *__dst);
> +
> +/* Retrieve class-dependent program header table.  */
> +extern Elf32_Phdr *elf32_getphdr (Elf *__elf);
> +/* Similar but this time the binary calls is ELFCLASS64.  */
> +extern Elf64_Phdr *elf64_getphdr (Elf *__elf);
> +
> +/* Create ELF program header.  */
> +extern Elf32_Phdr *elf32_newphdr (Elf *__elf, size_t __cnt);
> +/* Similar but this time the binary calls is ELFCLASS64.  */
> +extern Elf64_Phdr *elf64_newphdr (Elf *__elf, size_t __cnt);
> +
> +
> +/* Get section at INDEX.  */
> +extern Elf_Scn *elf_getscn (Elf *__elf, size_t __index);
> +
> +/* Get section at OFFSET.  */
> +extern Elf_Scn *elf32_offscn (Elf *__elf, Elf32_Off __offset);
> +/* Similar but this time the binary calls is ELFCLASS64.  */
> +extern Elf_Scn *elf64_offscn (Elf *__elf, Elf64_Off __offset);
> +
> +/* Get index of section.  */
> +extern size_t elf_ndxscn (Elf_Scn *__scn);
> +
> +/* Get section with next section index.  */
> +extern Elf_Scn *elf_nextscn (Elf *__elf, Elf_Scn *__scn);
> +
> +/* Create a new section and append it at the end of the table.  */
> +extern Elf_Scn *elf_newscn (Elf *__elf);
> +
> +/* Get the section index of the extended section index table for the
> +   given symbol table.  */
> +extern int elf_scnshndx (Elf_Scn *__scn);
> +
> +/* Get the number of sections in the ELF file.  If the file uses more
> +   sections than can be represented in the e_shnum field of the ELF
> +   header the information from the sh_size field in the zeroth section
> +   header is used.  */
> +extern int elf_getshdrnum (Elf *__elf, size_t *__dst);
> +/* Sun messed up the implementation of 'elf_getshnum' in their implementation.
> +   It was agreed to make the same functionality available under a different
> +   name and obsolete the old name.  */
> +extern int elf_getshnum (Elf *__elf, size_t *__dst)
> +     __deprecated_attribute__;
> +
> +
> +/* Get the section index of the section header string table in the ELF
> +   file.  If the index cannot be represented in the e_shstrndx field of
> +   the ELF header the information from the sh_link field in the zeroth
> +   section header is used.  */
> +extern int elf_getshdrstrndx (Elf *__elf, size_t *__dst);
> +/* Sun messed up the implementation of 'elf_getshstrndx' in their
> +   implementation.  It was agreed to make the same functionality available
> +   under a different name and obsolete the old name.  */
> +extern int elf_getshstrndx (Elf *__elf, size_t *__dst)
> +     __deprecated_attribute__;
> +
> +
> +/* Retrieve section header of ELFCLASS32 binary.  */
> +extern Elf32_Shdr *elf32_getshdr (Elf_Scn *__scn);
> +/* Similar for ELFCLASS64.  */
> +extern Elf64_Shdr *elf64_getshdr (Elf_Scn *__scn);
> +
> +/* Returns compression header for a section if section data is
> +   compressed.  Returns NULL and sets elf_errno if the section isn't
> +   compressed or an error occurred.  */
> +extern Elf32_Chdr *elf32_getchdr (Elf_Scn *__scn);
> +extern Elf64_Chdr *elf64_getchdr (Elf_Scn *__scn);
> +
> +/* Compress or decompress the data of a section and adjust the section
> +   header.
> +
> +   elf_compress works by setting or clearing the SHF_COMPRESS flag
> +   from the section Shdr and will encode or decode a Elf32_Chdr or
> +   Elf64_Chdr at the start of the section data.  elf_compress_gnu will
> +   encode or decode any section, but is traditionally only used for
> +   sections that have a name starting with ".debug" when
> +   uncompressed or ".zdebug" when compressed and stores just the
> +   uncompressed size.  The GNU compression method is deprecated and
> +   should only be used for legacy support.
> +
> +   elf_compress takes a compression type that should be either zero to
> +   decompress or an ELFCOMPRESS algorithm to use for compression.
> +   Currently ELFCOMPRESS_ZLIB and ELFCOMPRESS_ZSTD are supported.
> +   elf_compress_gnu will compress in the traditional GNU compression
> +   format when compress is one and decompress the section data when
> +   compress is zero.
> +
> +   The FLAGS argument can be zero or ELF_CHF_FORCE.  If FLAGS contains
> +   ELF_CHF_FORCE then it will always compress the section, even if
> +   that would not reduce the size of the data section (including the
> +   header).  Otherwise elf_compress and elf_compress_gnu will compress
> +   the section only if the total data size is reduced.
> +
> +   On successful compression or decompression the function returns
> +   one.  If (not forced) compression is requested and the data section
> +   would not actually reduce in size, the section is not actually
> +   compressed and zero is returned.  Otherwise -1 is returned and
> +   elf_errno is set.
> +
> +   It is an error to request compression for a section that already
> +   has SHF_COMPRESSED set, or (for elf_compress) to request
> +   decompression for an section that doesn't have SHF_COMPRESSED set.
> +   If a section has SHF_COMPRESSED set then calling elf_compress_gnu
> +   will result in an error.  The section has to be decompressed first
> +   using elf_compress.  Calling elf_compress on a section compressed
> +   with elf_compress_gnu is fine, but probably useless.
> +
> +   It is always an error to call these functions on SHT_NOBITS
> +   sections or if the section has the SHF_ALLOC flag set.
> +   elf_compress_gnu will not check whether the section name starts
> +   with ".debug" or .zdebug".  It is the responsibility of the caller
> +   to make sure the deprecated GNU compression method is only called
> +   on correctly named sections (and to change the name of the section
> +   when using elf_compress_gnu).
> +
> +   All previous returned Shdrs and Elf_Data buffers are invalidated by
> +   this call and should no longer be accessed.
> +
> +   Note that although this changes the header and data returned it
> +   doesn't mark the section as dirty.  To keep the changes when
> +   calling elf_update the section has to be flagged ELF_F_DIRTY.  */
> +extern int elf_compress (Elf_Scn *scn, int type, unsigned int flags);
> +extern int elf_compress_gnu (Elf_Scn *scn, int compress, unsigned int flags);
> +
> +/* Set or clear flags for ELF file.  */
> +extern unsigned int elf_flagelf (Elf *__elf, Elf_Cmd __cmd,
> +				 unsigned int __flags);
> +/* Similarly for the ELF header.  */
> +extern unsigned int elf_flagehdr (Elf *__elf, Elf_Cmd __cmd,
> +				  unsigned int __flags);
> +/* Similarly for the ELF program header.  */
> +extern unsigned int elf_flagphdr (Elf *__elf, Elf_Cmd __cmd,
> +				  unsigned int __flags);
> +/* Similarly for the given ELF section.  */
> +extern unsigned int elf_flagscn (Elf_Scn *__scn, Elf_Cmd __cmd,
> +				 unsigned int __flags);
> +/* Similarly for the given ELF data.  */
> +extern unsigned int elf_flagdata (Elf_Data *__data, Elf_Cmd __cmd,
> +				  unsigned int __flags);
> +/* Similarly for the given ELF section header.  */
> +extern unsigned int elf_flagshdr (Elf_Scn *__scn, Elf_Cmd __cmd,
> +				  unsigned int __flags);
> +
> +
> +/* Get data from section while translating from file representation to
> +   memory representation.  The Elf_Data d_type is set based on the
> +   section type if known.  Otherwise d_type is set to ELF_T_BYTE.  If
> +   the section contains compressed data then d_type is always set to
> +   ELF_T_CHDR.  */
> +extern Elf_Data *elf_getdata (Elf_Scn *__scn, Elf_Data *__data);
> +
> +/* Get uninterpreted section content.  */
> +extern Elf_Data *elf_rawdata (Elf_Scn *__scn, Elf_Data *__data);
> +
> +/* Create new data descriptor for section SCN.  */
> +extern Elf_Data *elf_newdata (Elf_Scn *__scn);
> +
> +/* Get data translated from a chunk of the file contents as section data
> +   would be for TYPE.  The resulting Elf_Data pointer is valid until
> +   elf_end (ELF) is called.  */
> +extern Elf_Data *elf_getdata_rawchunk (Elf *__elf,
> +				       int64_t __offset, size_t __size,
> +				       Elf_Type __type);
> +
> +
> +/* Return pointer to string at OFFSET in section INDEX.  */
> +extern char *elf_strptr (Elf *__elf, size_t __index, size_t __offset);
> +
> +
> +/* Return header of archive.  */
> +extern Elf_Arhdr *elf_getarhdr (Elf *__elf);
> +
> +/* Return offset in archive for current file ELF.  */
> +extern int64_t elf_getaroff (Elf *__elf);
> +
> +/* Select archive element at OFFSET.  */
> +extern size_t elf_rand (Elf *__elf, size_t __offset);
> +
> +/* Get symbol table of archive.  */
> +extern Elf_Arsym *elf_getarsym (Elf *__elf, size_t *__narsyms);
> +
> +
> +/* Control ELF descriptor.  */
> +extern int elf_cntl (Elf *__elf, Elf_Cmd __cmd);
> +
> +/* Retrieve uninterpreted file contents.  */
> +extern char *elf_rawfile (Elf *__elf, size_t *__nbytes);
> +
> +
> +/* Return size of array of COUNT elements of the type denoted by TYPE
> +   in the external representation.  The binary class is taken from ELF.
> +   The result is based on version VERSION of the ELF standard.  */
> +extern size_t elf32_fsize (Elf_Type __type, size_t __count,
> +			   unsigned int __version)
> +       __const_attribute__;
> +/* Similar but this time the binary calls is ELFCLASS64.  */
> +extern size_t elf64_fsize (Elf_Type __type, size_t __count,
> +			   unsigned int __version)
> +       __const_attribute__;
> +
> +
> +/* Convert data structure from the representation in the file represented
> +   by ELF to their memory representation.  */
> +extern Elf_Data *elf32_xlatetom (Elf_Data *__dest, const Elf_Data *__src,
> +				 unsigned int __encode);
> +/* Same for 64 bit class.  */
> +extern Elf_Data *elf64_xlatetom (Elf_Data *__dest, const Elf_Data *__src,
> +				 unsigned int __encode);
> +
> +/* Convert data structure from to the representation in memory
> +   represented by ELF file representation.  */
> +extern Elf_Data *elf32_xlatetof (Elf_Data *__dest, const Elf_Data *__src,
> +				 unsigned int __encode);
> +/* Same for 64 bit class.  */
> +extern Elf_Data *elf64_xlatetof (Elf_Data *__dest, const Elf_Data *__src,
> +				 unsigned int __encode);
> +
> +
> +/* Return error code of last failing function call.  This value is kept
> +   separately for each thread.  */
> +extern int elf_errno (void);
> +
> +/* Return error string for ERROR.  If ERROR is zero, return error string
> +   for most recent error or NULL is none occurred.  If ERROR is -1 the
> +   behaviour is similar to the last case except that not NULL but a legal
> +   string is returned.  */
> +extern const char *elf_errmsg (int __error);
> +
> +
> +/* Coordinate ELF library and application versions.  */
> +extern unsigned int elf_version (unsigned int __version);
> +
> +/* Set fill bytes used to fill holes in data structures.  */
> +extern void elf_fill (int __fill);
> +
> +/* Compute hash value.  */
> +extern unsigned long int elf_hash (const char *__string)
> +       __pure_attribute__;
> +
> +/* Compute hash value using the GNU-specific hash function.  */
> +extern unsigned long int elf_gnu_hash (const char *__string)
> +       __pure_attribute__;
> +
> +
> +/* Compute simple checksum from permanent parts of the ELF file.  */
> +extern long int elf32_checksum (Elf *__elf);
> +/* Similar but this time the binary calls is ELFCLASS64.  */
> +extern long int elf64_checksum (Elf *__elf);
> +
> +#ifdef __cplusplus
> +}
> +#endif
> +
> +#endif  /* libelf.h */
  
Ying Huang March 22, 2024, 2:20 a.m. UTC | #2
Ping,

Thanks.


在 2024/3/11 18:02, Ying Huang 写道:
> Hi Mark,
>
> Could you please review these patches, I have splited patch v2 1/5 to patch v3 1/6 and 2/6.
>
> Thanks,
>
> Ying
>
>
> 在 2024/3/5 17:51, Ying Huang 写道:
>> From: Ying Huang <ying.huang@oss.cipunited.com>
>>
>> Signed-off-by: Ying Huang <ying.huang@oss.cipunited.com>
>> ---
>>  backends/Makefile.am    |   6 +-
>>  backends/mips_init.c    |  52 ++++
>>  backends/mips_reloc.def |  93 +++++++
>>  backends/mips_symbol.c  |  63 +++++
>>  libebl/eblopenbackend.c |   2 +
>>  libelf/libelfP.h        |   3 +
>>  tests/libelf.h          | 541 ++++++++++++++++++++++++++++++++++++++++
>>  7 files changed, 758 insertions(+), 2 deletions(-)
>>  create mode 100644 backends/mips_init.c
>>  create mode 100644 backends/mips_reloc.def
>>  create mode 100644 backends/mips_symbol.c
>>  create mode 100644 tests/libelf.h
>>
>> diff --git a/backends/Makefile.am b/backends/Makefile.am
>> index bbb2aac7..b946fd30 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 \
>> @@ -102,12 +102,14 @@ loongarch_SRCS = loongarch_init.c loongarch_symbol.c loongarch_cfi.c \
>>  
>>  arc_SRCS = arc_init.c arc_symbol.c
>>  
>> +mips_SRCS = mips_init.c mips_symbol.c
>> +
>>  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..cedd08ca
>> --- /dev/null
>> +++ b/backends/mips_init.c
>> @@ -0,0 +1,52 @@
>> +/* Initialization of MIPS specific backend library.
>> +   Copyright (C) 2024 CIP United Inc.
>> +   This file is part of elfutils.
>> +
>> +   This file is free software; you can redistribute it and/or modify
>> +   it under the terms of either
>> +
>> +     * the GNU Lesser General Public License as published by the Free
>> +       Software Foundation; either version 3 of the License, or (at
>> +       your option) any later version
>> +
>> +   or
>> +
>> +     * the GNU General Public License as published by the Free
>> +       Software Foundation; either version 2 of the License, or (at
>> +       your option) any later version
>> +
>> +   or both in parallel, as here.
>> +
>> +   elfutils is distributed in the hope that it will be useful, but
>> +   WITHOUT ANY WARRANTY; without even the implied warranty of
>> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>> +   General Public License for more details.
>> +
>> +   You should have received copies of the GNU General Public License and
>> +   the GNU Lesser General Public License along with this program.  If
>> +   not, see <http://www.gnu.org/licenses/>.  */
>> +
>> +#ifdef HAVE_CONFIG_H
>> +# include <config.h>
>> +#endif
>> +
>> +#define BACKEND		mips_
>> +#define RELOC_PREFIX	R_MIPS_
>> +#include "libebl_CPU.h"
>> +#include "libelfP.h"
>> +
>> +#define RELOC_TYPE_ID(type) ((type) & 0xff)
>> +
>> +/* 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..5120980c
>> --- /dev/null
>> +++ b/backends/mips_reloc.def
>> @@ -0,0 +1,93 @@
>> +/* List the relocation types for MIPS.  -*- C -*-
>> +   Copyright (C) 2024 CIP United Inc.
>> +   This file is part of elfutils.
>> +
>> +   This file is free software; you can redistribute it and/or modify
>> +   it under the terms of either
>> +
>> +     * the GNU Lesser General Public License as published by the Free
>> +       Software Foundation; either version 3 of the License, or (at
>> +       your option) any later version
>> +
>> +   or
>> +
>> +     * the GNU General Public License as published by the Free
>> +       Software Foundation; either version 2 of the License, or (at
>> +       your option) any later version
>> +
>> +   or both in parallel, as here.
>> +
>> +   elfutils is distributed in the hope that it will be useful, but
>> +   WITHOUT ANY WARRANTY; without even the implied warranty of
>> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>> +   General Public License for more details.
>> +
>> +   You should have received copies of the GNU General Public License and
>> +   the GNU Lesser General Public License along with this program.  If
>> +   not, see <http://www.gnu.org/licenses/>.  */
>> +
>> +/*	    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..f2a46495
>> --- /dev/null
>> +++ b/backends/mips_symbol.c
>> @@ -0,0 +1,63 @@
>> +/* MIPS specific symbolic name handling.
>> +   Copyright (C) 2024 CIP United Inc.
>> +   This file is part of elfutils.
>> +
>> +   This file is free software; you can redistribute it and/or modify
>> +   it under the terms of either
>> +
>> +     * the GNU Lesser General Public License as published by the Free
>> +       Software Foundation; either version 3 of the License, or (at
>> +       your option) any later version
>> +
>> +   or
>> +
>> +     * the GNU General Public License as published by the Free
>> +       Software Foundation; either version 2 of the License, or (at
>> +       your option) any later version
>> +
>> +   or both in parallel, as here.
>> +
>> +   elfutils is distributed in the hope that it will be useful, but
>> +   WITHOUT ANY WARRANTY; without even the implied warranty of
>> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>> +   General Public License for more details.
>> +
>> +   You should have received copies of the GNU General Public License and
>> +   the GNU Lesser General Public License along with this program.  If
>> +   not, see <http://www.gnu.org/licenses/>.  */
>> +
>> +#ifdef HAVE_CONFIG_H
>> +# include <config.h>
>> +#endif
>> +
>> +#include <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_TYPE1(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/libelfP.h b/libelf/libelfP.h
>> index ed061abb..bdd2cc6a 100644
>> --- a/libelf/libelfP.h
>> +++ b/libelf/libelfP.h
>> @@ -617,4 +617,7 @@ extern void __libelf_reset_rawdata (Elf_Scn *scn, void *buf, size_t size,
>>  #define INVALID_NDX(ndx, type, data) \
>>    unlikely ((data)->d_size / sizeof (type) <= (unsigned int) (ndx))
>>  
>> +#define ELF64_MIPS_R_TYPE1(i)          ((i) & 0xff)
>> +#define ELF64_MIPS_R_TYPE2(i)           (((i) >> 8) & 0xff)
>> +#define ELF64_MIPS_R_TYPE3(i)           (((i) >> 16) & 0xff)
>>  #endif  /* libelfP.h */
>> diff --git a/tests/libelf.h b/tests/libelf.h
>> new file mode 100644
>> index 00000000..d3f057b4
>> --- /dev/null
>> +++ b/tests/libelf.h
>> @@ -0,0 +1,541 @@
>> +/* Interface for libelf.
>> +   Copyright (C) 1998-2010, 2015 Red Hat, 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/>.  */
>> +
>> +#ifndef _LIBELF_H
>> +#define _LIBELF_H 1
>> +
>> +#include <stdint.h>
>> +#include <sys/types.h>
>> +
>> +/* Get the ELF types.  */
>> +#include <elf.h>
>> +
>> +#ifndef SHF_COMPRESSED
>> + /* Older glibc elf.h might not yet define the ELF compression types.  */
>> + #define SHF_COMPRESSED      (1 << 11)  /* Section with compressed data. */
>> +
>> + /* Section compression header.  Used when SHF_COMPRESSED is set.  */
>> +
>> + typedef struct
>> + {
>> +   Elf32_Word   ch_type;        /* Compression format.  */
>> +   Elf32_Word   ch_size;        /* Uncompressed data size.  */
>> +   Elf32_Word   ch_addralign;   /* Uncompressed data alignment.  */
>> + } Elf32_Chdr;
>> +
>> + typedef struct
>> + {
>> +   Elf64_Word   ch_type;        /* Compression format.  */
>> +   Elf64_Word   ch_reserved;
>> +   Elf64_Xword  ch_size;        /* Uncompressed data size.  */
>> +   Elf64_Xword  ch_addralign;   /* Uncompressed data alignment.  */
>> + } Elf64_Chdr;
>> +
>> + /* Legal values for ch_type (compression algorithm).  */
>> + #define ELFCOMPRESS_ZLIB       1          /* ZLIB/DEFLATE algorithm.  */
>> + #define ELFCOMPRESS_LOOS       0x60000000 /* Start of OS-specific.  */
>> + #define ELFCOMPRESS_HIOS       0x6fffffff /* End of OS-specific.  */
>> + #define ELFCOMPRESS_LOPROC     0x70000000 /* Start of processor-specific.  */
>> + #define ELFCOMPRESS_HIPROC     0x7fffffff /* End of processor-specific.  */
>> +#endif
>> +
>> +#ifndef ELFCOMPRESS_ZSTD
>> + /* So ZSTD compression can be used even with an old system elf.h.  */
>> + #define ELFCOMPRESS_ZSTD       2          /* Zstandard algorithm.  */
>> +#endif
>> +
>> +#ifndef SHT_RELR
>> + /* So RELR defines/typedefs can be used even with an old system elf.h.  */
>> + #define SHT_RELR       19      /* RELR relative relocations */
>> +
>> + /* RELR relocation table entry */
>> + typedef Elf32_Word     Elf32_Relr;
>> + typedef Elf64_Xword    Elf64_Relr;
>> +
>> + #define DT_RELRSZ      35      /* Total size of RELR relative relocations */
>> + #define DT_RELR        36      /* Address of RELR relative relocations */
>> + #define DT_RELRENT     37      /* Size of one RELR relative relocaction */
>> +#endif
>> +
>> +#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)
>> +# define __nonnull_attribute__(...) __attribute__ ((__nonnull__ (__VA_ARGS__)))
>> +# define __deprecated_attribute__ __attribute__ ((__deprecated__))
>> +# define __pure_attribute__ __attribute__ ((__pure__))
>> +# define __const_attribute__ __attribute__ ((__const__))
>> +#else
>> +# define __nonnull_attribute__(...)
>> +# define __deprecated_attribute__
>> +# define __pure_attribute__
>> +# define __const_attribute__
>> +#endif
>> +
>> +#if __GNUC__ < 4
>> +#define __noreturn_attribute__
>> +#else
>> +#define __noreturn_attribute__ __attribute__ ((noreturn))
>> +#endif
>> +
>> +#ifdef __GNUC_STDC_INLINE__
>> +# define __libdw_extern_inline extern __inline __attribute__ ((__gnu_inline__))
>> +#else
>> +# define __libdw_extern_inline extern __inline
>> +#endif
>> +
>> +/* Known translation types.  */
>> +typedef enum
>> +{
>> +  ELF_T_BYTE,                   /* unsigned char */
>> +  ELF_T_ADDR,                   /* Elf32_Addr, Elf64_Addr, ... */
>> +  ELF_T_DYN,                    /* Dynamic section record.  */
>> +  ELF_T_EHDR,                   /* ELF header.  */
>> +  ELF_T_HALF,                   /* Elf32_Half, Elf64_Half, ... */
>> +  ELF_T_OFF,                    /* Elf32_Off, Elf64_Off, ... */
>> +  ELF_T_PHDR,                   /* Program header.  */
>> +  ELF_T_RELA,                   /* Relocation entry with addend.  */
>> +  ELF_T_REL,                    /* Relocation entry.  */
>> +  ELF_T_SHDR,                   /* Section header.  */
>> +  ELF_T_SWORD,                  /* Elf32_Sword, Elf64_Sword, ... */
>> +  ELF_T_SYM,                    /* Symbol record.  */
>> +  ELF_T_WORD,                   /* Elf32_Word, Elf64_Word, ... */
>> +  ELF_T_XWORD,                  /* Elf32_Xword, Elf64_Xword, ... */
>> +  ELF_T_SXWORD,                 /* Elf32_Sxword, Elf64_Sxword, ... */
>> +  ELF_T_VDEF,                   /* Elf32_Verdef, Elf64_Verdef, ... */
>> +  ELF_T_VDAUX,                  /* Elf32_Verdaux, Elf64_Verdaux, ... */
>> +  ELF_T_VNEED,                  /* Elf32_Verneed, Elf64_Verneed, ... */
>> +  ELF_T_VNAUX,                  /* Elf32_Vernaux, Elf64_Vernaux, ... */
>> +  ELF_T_NHDR,                   /* Elf32_Nhdr, Elf64_Nhdr, ... */
>> +  ELF_T_SYMINFO,		/* Elf32_Syminfo, Elf64_Syminfo, ... */
>> +  ELF_T_MOVE,			/* Elf32_Move, Elf64_Move, ... */
>> +  ELF_T_LIB,			/* Elf32_Lib, Elf64_Lib, ... */
>> +  ELF_T_GNUHASH,		/* GNU-style hash section.  */
>> +  ELF_T_AUXV,			/* Elf32_auxv_t, Elf64_auxv_t, ... */
>> +  ELF_T_CHDR,			/* Compressed, Elf32_Chdr, Elf64_Chdr, ... */
>> +  ELF_T_NHDR8,			/* Special GNU Properties note.  Same as Nhdr,
>> +				   except padding.  */
>> +  ELF_T_RELR,			/* Relative relocation entry.  */
>> +  /* Keep this the last entry.  */
>> +  ELF_T_NUM
>> +} Elf_Type;
>> +
>> +/* Descriptor for data to be converted to or from memory format.  */
>> +typedef struct
>> +{
>> +  void *d_buf;			/* Pointer to the actual data.  */
>> +  Elf_Type d_type;		/* Type of this piece of data.  */
>> +  unsigned int d_version;	/* ELF version.  */
>> +  size_t d_size;		/* Size in bytes.  */
>> +  int64_t d_off;		/* Offset into section.  */
>> +  size_t d_align;		/* Alignment in section.  */
>> +} Elf_Data;
>> +
>> +
>> +/* Commands for `...'.  */
>> +typedef enum
>> +{
>> +  ELF_C_NULL,			/* Nothing, terminate, or compute only.  */
>> +  ELF_C_READ,			/* Read .. */
>> +  ELF_C_RDWR,			/* Read and write .. */
>> +  ELF_C_WRITE,			/* Write .. */
>> +  ELF_C_CLR,			/* Clear flag.  */
>> +  ELF_C_SET,			/* Set flag.  */
>> +  ELF_C_FDDONE,			/* Signal that file descriptor will not be
>> +				   used anymore.  */
>> +  ELF_C_FDREAD,			/* Read rest of data so that file descriptor
>> +				   is not used anymore.  */
>> +  /* The following are extensions.  */
>> +  ELF_C_READ_MMAP,		/* Read, but mmap the file if possible.  */
>> +  ELF_C_RDWR_MMAP,		/* Read and write, with mmap.  */
>> +  ELF_C_WRITE_MMAP,		/* Write, with mmap.  */
>> +  ELF_C_READ_MMAP_PRIVATE,	/* Read, but memory is writable, results are
>> +				   not written to the file.  */
>> +  ELF_C_EMPTY,			/* Copy basic file data but not the content. */
>> +  /* Keep this the last entry.  */
>> +  ELF_C_NUM
>> +} Elf_Cmd;
>> +
>> +
>> +/* Flags for the ELF structures.  */
>> +enum
>> +{
>> +  ELF_F_DIRTY = 0x1,
>> +#define ELF_F_DIRTY		ELF_F_DIRTY
>> +  ELF_F_LAYOUT = 0x4,
>> +#define ELF_F_LAYOUT		ELF_F_LAYOUT
>> +  ELF_F_PERMISSIVE = 0x8
>> +#define ELF_F_PERMISSIVE	ELF_F_PERMISSIVE
>> +};
>> +
>> +/* Flags for elf_compress[_gnu].  */
>> +enum
>> +{
>> +  ELF_CHF_FORCE = 0x1
>> +#define ELF_CHF_FORCE ELF_CHF_FORCE
>> +};
>> +
>> +/* Identification values for recognized object files.  */
>> +typedef enum
>> +{
>> +  ELF_K_NONE,			/* Unknown.  */
>> +  ELF_K_AR,			/* Archive.  */
>> +  ELF_K_COFF,			/* Stupid old COFF.  */
>> +  ELF_K_ELF,			/* ELF file.  */
>> +  /* Keep this the last entry.  */
>> +  ELF_K_NUM
>> +} Elf_Kind;
>> +
>> +
>> +/* Archive member header.  */
>> +typedef struct
>> +{
>> +  char *ar_name;		/* Name of archive member.  */
>> +  time_t ar_date;		/* File date.  */
>> +  uid_t ar_uid;			/* User ID.  */
>> +  gid_t ar_gid;			/* Group ID.  */
>> +  mode_t ar_mode;		/* File mode.  */
>> +  int64_t ar_size;		/* File size.  */
>> +  char *ar_rawname;		/* Original name of archive member.  */
>> +} Elf_Arhdr;
>> +
>> +
>> +/* Archive symbol table entry.  */
>> +typedef struct
>> +{
>> +  char *as_name;		/* Symbol name.  */
>> +  size_t as_off;		/* Offset for this file in the archive.  */
>> +  unsigned long int as_hash;	/* Hash value of the name.  */
>> +} Elf_Arsym;
>> +
>> +
>> +/* Descriptor for the ELF file.  */
>> +typedef struct Elf Elf;
>> +
>> +/* Descriptor for ELF file section.  */
>> +typedef struct Elf_Scn Elf_Scn;
>> +
>> +
>> +#ifdef __cplusplus
>> +extern "C" {
>> +#endif
>> +
>> +/* Return descriptor for ELF file to work according to CMD.  */
>> +extern Elf *elf_begin (int __fildes, Elf_Cmd __cmd, Elf *__ref);
>> +
>> +/* Create a clone of an existing ELF descriptor.  */
>> +  extern Elf *elf_clone (Elf *__elf, Elf_Cmd __cmd);
>> +
>> +/* Create descriptor for memory region.  */
>> +extern Elf *elf_memory (char *__image, size_t __size);
>> +
>> +/* Advance archive descriptor to next element.  */
>> +extern Elf_Cmd elf_next (Elf *__elf);
>> +
>> +/* Free resources allocated for ELF.  */
>> +extern int elf_end (Elf *__elf);
>> +
>> +/* Update ELF descriptor and write file to disk.  */
>> +extern int64_t elf_update (Elf *__elf, Elf_Cmd __cmd);
>> +
>> +/* Determine what kind of file is associated with ELF.  */
>> +extern Elf_Kind elf_kind (Elf *__elf) __pure_attribute__;
>> +
>> +/* Get the base offset for an object file.  */
>> +extern int64_t elf_getbase (Elf *__elf);
>> +
>> +
>> +/* Retrieve file identification data.  */
>> +extern char *elf_getident (Elf *__elf, size_t *__nbytes);
>> +
>> +/* Retrieve class-dependent object file header.  */
>> +extern Elf32_Ehdr *elf32_getehdr (Elf *__elf);
>> +/* Similar but this time the binary calls is ELFCLASS64.  */
>> +extern Elf64_Ehdr *elf64_getehdr (Elf *__elf);
>> +
>> +/* Create ELF header if none exists.  */
>> +extern Elf32_Ehdr *elf32_newehdr (Elf *__elf);
>> +/* Similar but this time the binary calls is ELFCLASS64.  */
>> +extern Elf64_Ehdr *elf64_newehdr (Elf *__elf);
>> +
>> +/* Get the number of program headers in the ELF file.  If the file uses
>> +   more headers than can be represented in the e_phnum field of the ELF
>> +   header the information from the sh_info field in the zeroth section
>> +   header is used.  */
>> +extern int elf_getphdrnum (Elf *__elf, size_t *__dst);
>> +
>> +/* Retrieve class-dependent program header table.  */
>> +extern Elf32_Phdr *elf32_getphdr (Elf *__elf);
>> +/* Similar but this time the binary calls is ELFCLASS64.  */
>> +extern Elf64_Phdr *elf64_getphdr (Elf *__elf);
>> +
>> +/* Create ELF program header.  */
>> +extern Elf32_Phdr *elf32_newphdr (Elf *__elf, size_t __cnt);
>> +/* Similar but this time the binary calls is ELFCLASS64.  */
>> +extern Elf64_Phdr *elf64_newphdr (Elf *__elf, size_t __cnt);
>> +
>> +
>> +/* Get section at INDEX.  */
>> +extern Elf_Scn *elf_getscn (Elf *__elf, size_t __index);
>> +
>> +/* Get section at OFFSET.  */
>> +extern Elf_Scn *elf32_offscn (Elf *__elf, Elf32_Off __offset);
>> +/* Similar but this time the binary calls is ELFCLASS64.  */
>> +extern Elf_Scn *elf64_offscn (Elf *__elf, Elf64_Off __offset);
>> +
>> +/* Get index of section.  */
>> +extern size_t elf_ndxscn (Elf_Scn *__scn);
>> +
>> +/* Get section with next section index.  */
>> +extern Elf_Scn *elf_nextscn (Elf *__elf, Elf_Scn *__scn);
>> +
>> +/* Create a new section and append it at the end of the table.  */
>> +extern Elf_Scn *elf_newscn (Elf *__elf);
>> +
>> +/* Get the section index of the extended section index table for the
>> +   given symbol table.  */
>> +extern int elf_scnshndx (Elf_Scn *__scn);
>> +
>> +/* Get the number of sections in the ELF file.  If the file uses more
>> +   sections than can be represented in the e_shnum field of the ELF
>> +   header the information from the sh_size field in the zeroth section
>> +   header is used.  */
>> +extern int elf_getshdrnum (Elf *__elf, size_t *__dst);
>> +/* Sun messed up the implementation of 'elf_getshnum' in their implementation.
>> +   It was agreed to make the same functionality available under a different
>> +   name and obsolete the old name.  */
>> +extern int elf_getshnum (Elf *__elf, size_t *__dst)
>> +     __deprecated_attribute__;
>> +
>> +
>> +/* Get the section index of the section header string table in the ELF
>> +   file.  If the index cannot be represented in the e_shstrndx field of
>> +   the ELF header the information from the sh_link field in the zeroth
>> +   section header is used.  */
>> +extern int elf_getshdrstrndx (Elf *__elf, size_t *__dst);
>> +/* Sun messed up the implementation of 'elf_getshstrndx' in their
>> +   implementation.  It was agreed to make the same functionality available
>> +   under a different name and obsolete the old name.  */
>> +extern int elf_getshstrndx (Elf *__elf, size_t *__dst)
>> +     __deprecated_attribute__;
>> +
>> +
>> +/* Retrieve section header of ELFCLASS32 binary.  */
>> +extern Elf32_Shdr *elf32_getshdr (Elf_Scn *__scn);
>> +/* Similar for ELFCLASS64.  */
>> +extern Elf64_Shdr *elf64_getshdr (Elf_Scn *__scn);
>> +
>> +/* Returns compression header for a section if section data is
>> +   compressed.  Returns NULL and sets elf_errno if the section isn't
>> +   compressed or an error occurred.  */
>> +extern Elf32_Chdr *elf32_getchdr (Elf_Scn *__scn);
>> +extern Elf64_Chdr *elf64_getchdr (Elf_Scn *__scn);
>> +
>> +/* Compress or decompress the data of a section and adjust the section
>> +   header.
>> +
>> +   elf_compress works by setting or clearing the SHF_COMPRESS flag
>> +   from the section Shdr and will encode or decode a Elf32_Chdr or
>> +   Elf64_Chdr at the start of the section data.  elf_compress_gnu will
>> +   encode or decode any section, but is traditionally only used for
>> +   sections that have a name starting with ".debug" when
>> +   uncompressed or ".zdebug" when compressed and stores just the
>> +   uncompressed size.  The GNU compression method is deprecated and
>> +   should only be used for legacy support.
>> +
>> +   elf_compress takes a compression type that should be either zero to
>> +   decompress or an ELFCOMPRESS algorithm to use for compression.
>> +   Currently ELFCOMPRESS_ZLIB and ELFCOMPRESS_ZSTD are supported.
>> +   elf_compress_gnu will compress in the traditional GNU compression
>> +   format when compress is one and decompress the section data when
>> +   compress is zero.
>> +
>> +   The FLAGS argument can be zero or ELF_CHF_FORCE.  If FLAGS contains
>> +   ELF_CHF_FORCE then it will always compress the section, even if
>> +   that would not reduce the size of the data section (including the
>> +   header).  Otherwise elf_compress and elf_compress_gnu will compress
>> +   the section only if the total data size is reduced.
>> +
>> +   On successful compression or decompression the function returns
>> +   one.  If (not forced) compression is requested and the data section
>> +   would not actually reduce in size, the section is not actually
>> +   compressed and zero is returned.  Otherwise -1 is returned and
>> +   elf_errno is set.
>> +
>> +   It is an error to request compression for a section that already
>> +   has SHF_COMPRESSED set, or (for elf_compress) to request
>> +   decompression for an section that doesn't have SHF_COMPRESSED set.
>> +   If a section has SHF_COMPRESSED set then calling elf_compress_gnu
>> +   will result in an error.  The section has to be decompressed first
>> +   using elf_compress.  Calling elf_compress on a section compressed
>> +   with elf_compress_gnu is fine, but probably useless.
>> +
>> +   It is always an error to call these functions on SHT_NOBITS
>> +   sections or if the section has the SHF_ALLOC flag set.
>> +   elf_compress_gnu will not check whether the section name starts
>> +   with ".debug" or .zdebug".  It is the responsibility of the caller
>> +   to make sure the deprecated GNU compression method is only called
>> +   on correctly named sections (and to change the name of the section
>> +   when using elf_compress_gnu).
>> +
>> +   All previous returned Shdrs and Elf_Data buffers are invalidated by
>> +   this call and should no longer be accessed.
>> +
>> +   Note that although this changes the header and data returned it
>> +   doesn't mark the section as dirty.  To keep the changes when
>> +   calling elf_update the section has to be flagged ELF_F_DIRTY.  */
>> +extern int elf_compress (Elf_Scn *scn, int type, unsigned int flags);
>> +extern int elf_compress_gnu (Elf_Scn *scn, int compress, unsigned int flags);
>> +
>> +/* Set or clear flags for ELF file.  */
>> +extern unsigned int elf_flagelf (Elf *__elf, Elf_Cmd __cmd,
>> +				 unsigned int __flags);
>> +/* Similarly for the ELF header.  */
>> +extern unsigned int elf_flagehdr (Elf *__elf, Elf_Cmd __cmd,
>> +				  unsigned int __flags);
>> +/* Similarly for the ELF program header.  */
>> +extern unsigned int elf_flagphdr (Elf *__elf, Elf_Cmd __cmd,
>> +				  unsigned int __flags);
>> +/* Similarly for the given ELF section.  */
>> +extern unsigned int elf_flagscn (Elf_Scn *__scn, Elf_Cmd __cmd,
>> +				 unsigned int __flags);
>> +/* Similarly for the given ELF data.  */
>> +extern unsigned int elf_flagdata (Elf_Data *__data, Elf_Cmd __cmd,
>> +				  unsigned int __flags);
>> +/* Similarly for the given ELF section header.  */
>> +extern unsigned int elf_flagshdr (Elf_Scn *__scn, Elf_Cmd __cmd,
>> +				  unsigned int __flags);
>> +
>> +
>> +/* Get data from section while translating from file representation to
>> +   memory representation.  The Elf_Data d_type is set based on the
>> +   section type if known.  Otherwise d_type is set to ELF_T_BYTE.  If
>> +   the section contains compressed data then d_type is always set to
>> +   ELF_T_CHDR.  */
>> +extern Elf_Data *elf_getdata (Elf_Scn *__scn, Elf_Data *__data);
>> +
>> +/* Get uninterpreted section content.  */
>> +extern Elf_Data *elf_rawdata (Elf_Scn *__scn, Elf_Data *__data);
>> +
>> +/* Create new data descriptor for section SCN.  */
>> +extern Elf_Data *elf_newdata (Elf_Scn *__scn);
>> +
>> +/* Get data translated from a chunk of the file contents as section data
>> +   would be for TYPE.  The resulting Elf_Data pointer is valid until
>> +   elf_end (ELF) is called.  */
>> +extern Elf_Data *elf_getdata_rawchunk (Elf *__elf,
>> +				       int64_t __offset, size_t __size,
>> +				       Elf_Type __type);
>> +
>> +
>> +/* Return pointer to string at OFFSET in section INDEX.  */
>> +extern char *elf_strptr (Elf *__elf, size_t __index, size_t __offset);
>> +
>> +
>> +/* Return header of archive.  */
>> +extern Elf_Arhdr *elf_getarhdr (Elf *__elf);
>> +
>> +/* Return offset in archive for current file ELF.  */
>> +extern int64_t elf_getaroff (Elf *__elf);
>> +
>> +/* Select archive element at OFFSET.  */
>> +extern size_t elf_rand (Elf *__elf, size_t __offset);
>> +
>> +/* Get symbol table of archive.  */
>> +extern Elf_Arsym *elf_getarsym (Elf *__elf, size_t *__narsyms);
>> +
>> +
>> +/* Control ELF descriptor.  */
>> +extern int elf_cntl (Elf *__elf, Elf_Cmd __cmd);
>> +
>> +/* Retrieve uninterpreted file contents.  */
>> +extern char *elf_rawfile (Elf *__elf, size_t *__nbytes);
>> +
>> +
>> +/* Return size of array of COUNT elements of the type denoted by TYPE
>> +   in the external representation.  The binary class is taken from ELF.
>> +   The result is based on version VERSION of the ELF standard.  */
>> +extern size_t elf32_fsize (Elf_Type __type, size_t __count,
>> +			   unsigned int __version)
>> +       __const_attribute__;
>> +/* Similar but this time the binary calls is ELFCLASS64.  */
>> +extern size_t elf64_fsize (Elf_Type __type, size_t __count,
>> +			   unsigned int __version)
>> +       __const_attribute__;
>> +
>> +
>> +/* Convert data structure from the representation in the file represented
>> +   by ELF to their memory representation.  */
>> +extern Elf_Data *elf32_xlatetom (Elf_Data *__dest, const Elf_Data *__src,
>> +				 unsigned int __encode);
>> +/* Same for 64 bit class.  */
>> +extern Elf_Data *elf64_xlatetom (Elf_Data *__dest, const Elf_Data *__src,
>> +				 unsigned int __encode);
>> +
>> +/* Convert data structure from to the representation in memory
>> +   represented by ELF file representation.  */
>> +extern Elf_Data *elf32_xlatetof (Elf_Data *__dest, const Elf_Data *__src,
>> +				 unsigned int __encode);
>> +/* Same for 64 bit class.  */
>> +extern Elf_Data *elf64_xlatetof (Elf_Data *__dest, const Elf_Data *__src,
>> +				 unsigned int __encode);
>> +
>> +
>> +/* Return error code of last failing function call.  This value is kept
>> +   separately for each thread.  */
>> +extern int elf_errno (void);
>> +
>> +/* Return error string for ERROR.  If ERROR is zero, return error string
>> +   for most recent error or NULL is none occurred.  If ERROR is -1 the
>> +   behaviour is similar to the last case except that not NULL but a legal
>> +   string is returned.  */
>> +extern const char *elf_errmsg (int __error);
>> +
>> +
>> +/* Coordinate ELF library and application versions.  */
>> +extern unsigned int elf_version (unsigned int __version);
>> +
>> +/* Set fill bytes used to fill holes in data structures.  */
>> +extern void elf_fill (int __fill);
>> +
>> +/* Compute hash value.  */
>> +extern unsigned long int elf_hash (const char *__string)
>> +       __pure_attribute__;
>> +
>> +/* Compute hash value using the GNU-specific hash function.  */
>> +extern unsigned long int elf_gnu_hash (const char *__string)
>> +       __pure_attribute__;
>> +
>> +
>> +/* Compute simple checksum from permanent parts of the ELF file.  */
>> +extern long int elf32_checksum (Elf *__elf);
>> +/* Similar but this time the binary calls is ELFCLASS64.  */
>> +extern long int elf64_checksum (Elf *__elf);
>> +
>> +#ifdef __cplusplus
>> +}
>> +#endif
>> +
>> +#endif  /* libelf.h */
  
Mark Wielaard March 29, 2024, 12:18 a.m. UTC | #3
Hi Ying,

On Tue, Mar 05, 2024 at 05:51:17PM +0800, Ying Huang wrote:
> From: Ying Huang <ying.huang@oss.cipunited.com>
> 
> Signed-off-by: Ying Huang <ying.huang@oss.cipunited.com>
> ---
>  backends/Makefile.am    |   6 +-
>  backends/mips_init.c    |  52 ++++
>  backends/mips_reloc.def |  93 +++++++
>  backends/mips_symbol.c  |  63 +++++
>  libebl/eblopenbackend.c |   2 +
>  libelf/libelfP.h        |   3 +
>  tests/libelf.h          | 541 ++++++++++++++++++++++++++++++++++++++++

Note that this adds tests/libelf.h by accident.  I see how that could
happen, because it should have been in .gitignore.  I posted a patch
to do that:
https://inbox.sourceware.org/elfutils-devel/20240328234308.1032110-1-mark@klomp.org/

Besides that the patch looks fine. I did add a ChangeLog entry to the
commit message. Pushed as attached.

Thanks,

Mark
From e259f126f5077923e415e306915de50ed0f0db56 Mon Sep 17 00:00:00 2001
From: Ying Huang <ying.huang@oss.cipunited.com>
Date: Tue, 5 Mar 2024 17:51:17 +0800
Subject: [PATCH] Support Mips architecture

	* backends/Makefile.am (modules): Add mips.
	(mips_SRCS): New var for mips_init.c mips_symbol.c.
	(libebl_backends_a_SOURCES): Add mips_SRCS.
	* backends/mips_init.c: New file.
	* backends/mips_reloc.def: Likewise.
	* backends/mips_symbol.c: Likewise.
	* libebl/eblopenbackend.c (mips_init): Declare.
	(machines): Add mips.
	* libelf/libelfP.h: Add ELF64_MIPS_R_TYPE{1,2,3}

Signed-off-by: Ying Huang <ying.huang@oss.cipunited.com>
---
 backends/Makefile.am    |  6 ++-
 backends/mips_init.c    | 52 +++++++++++++++++++++++
 backends/mips_reloc.def | 93 +++++++++++++++++++++++++++++++++++++++++
 backends/mips_symbol.c  | 63 ++++++++++++++++++++++++++++
 libebl/eblopenbackend.c |  2 +
 libelf/libelfP.h        |  3 ++
 6 files changed, 217 insertions(+), 2 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 bbb2aac79ab8..b946fd30495f 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 \
@@ -102,12 +102,14 @@ loongarch_SRCS = loongarch_init.c loongarch_symbol.c loongarch_cfi.c \
 
 arc_SRCS = arc_init.c arc_symbol.c
 
+mips_SRCS = mips_init.c mips_symbol.c
+
 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 000000000000..cedd08ca1339
--- /dev/null
+++ b/backends/mips_init.c
@@ -0,0 +1,52 @@
+/* Initialization of MIPS specific backend library.
+   Copyright (C) 2024 CIP United Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#define BACKEND		mips_
+#define RELOC_PREFIX	R_MIPS_
+#include "libebl_CPU.h"
+#include "libelfP.h"
+
+#define RELOC_TYPE_ID(type) ((type) & 0xff)
+
+/* 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 000000000000..5120980c13eb
--- /dev/null
+++ b/backends/mips_reloc.def
@@ -0,0 +1,93 @@
+/* List the relocation types for MIPS.  -*- C -*-
+   Copyright (C) 2024 CIP United Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+/*	    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 000000000000..f2a46495ed6b
--- /dev/null
+++ b/backends/mips_symbol.c
@@ -0,0 +1,63 @@
+/* MIPS specific symbolic name handling.
+   Copyright (C) 2024 CIP United Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <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_TYPE1(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 084a1544b286..a5f7467a09d2 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/libelfP.h b/libelf/libelfP.h
index ed061abb0066..bdd2cc6ac27d 100644
--- a/libelf/libelfP.h
+++ b/libelf/libelfP.h
@@ -617,4 +617,7 @@ extern void __libelf_reset_rawdata (Elf_Scn *scn, void *buf, size_t size,
 #define INVALID_NDX(ndx, type, data) \
   unlikely ((data)->d_size / sizeof (type) <= (unsigned int) (ndx))
 
+#define ELF64_MIPS_R_TYPE1(i)          ((i) & 0xff)
+#define ELF64_MIPS_R_TYPE2(i)           (((i) >> 8) & 0xff)
+#define ELF64_MIPS_R_TYPE3(i)           (((i) >> 16) & 0xff)
 #endif  /* libelfP.h */
  
Ying Huang March 29, 2024, 7:40 a.m. UTC | #4
Hi Mark,

Next time I send a patch, I will add ChangeLog entry in commit message and check the added file.

Thanks,

Ying


在 2024/3/29 08:18, Mark Wielaard 写道:
> Hi Ying,
>
> On Tue, Mar 05, 2024 at 05:51:17PM +0800, Ying Huang wrote:
>> From: Ying Huang <ying.huang@oss.cipunited.com>
>>
>> Signed-off-by: Ying Huang <ying.huang@oss.cipunited.com>
>> ---
>>  backends/Makefile.am    |   6 +-
>>  backends/mips_init.c    |  52 ++++
>>  backends/mips_reloc.def |  93 +++++++
>>  backends/mips_symbol.c  |  63 +++++
>>  libebl/eblopenbackend.c |   2 +
>>  libelf/libelfP.h        |   3 +
>>  tests/libelf.h          | 541 ++++++++++++++++++++++++++++++++++++++++
> Note that this adds tests/libelf.h by accident.  I see how that could
> happen, because it should have been in .gitignore.  I posted a patch
> to do that:
> https://inbox.sourceware.org/elfutils-devel/20240328234308.1032110-1-mark@klomp.org/
>
> Besides that the patch looks fine. I did add a ChangeLog entry to the
> commit message. Pushed as attached.
>
> Thanks,
>
> Mark
  
Ying Huang April 3, 2024, 9:36 a.m. UTC | #5
Hi Mark,

Could you help review some other patches?

Thanks,

Ying


在 2024/3/29 08:18, Mark Wielaard 写道:
> Hi Ying,
>
> On Tue, Mar 05, 2024 at 05:51:17PM +0800, Ying Huang wrote:
>> From: Ying Huang <ying.huang@oss.cipunited.com>
>>
>> Signed-off-by: Ying Huang <ying.huang@oss.cipunited.com>
>> ---
>>  backends/Makefile.am    |   6 +-
>>  backends/mips_init.c    |  52 ++++
>>  backends/mips_reloc.def |  93 +++++++
>>  backends/mips_symbol.c  |  63 +++++
>>  libebl/eblopenbackend.c |   2 +
>>  libelf/libelfP.h        |   3 +
>>  tests/libelf.h          | 541 ++++++++++++++++++++++++++++++++++++++++
> Note that this adds tests/libelf.h by accident.  I see how that could
> happen, because it should have been in .gitignore.  I posted a patch
> to do that:
> https://inbox.sourceware.org/elfutils-devel/20240328234308.1032110-1-mark@klomp.org/
>
> Besides that the patch looks fine. I did add a ChangeLog entry to the
> commit message. Pushed as attached.
>
> Thanks,
>
> Mark
  

Patch

diff --git a/backends/Makefile.am b/backends/Makefile.am
index bbb2aac7..b946fd30 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 \
@@ -102,12 +102,14 @@  loongarch_SRCS = loongarch_init.c loongarch_symbol.c loongarch_cfi.c \
 
 arc_SRCS = arc_init.c arc_symbol.c
 
+mips_SRCS = mips_init.c mips_symbol.c
+
 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..cedd08ca
--- /dev/null
+++ b/backends/mips_init.c
@@ -0,0 +1,52 @@ 
+/* Initialization of MIPS specific backend library.
+   Copyright (C) 2024 CIP United Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#define BACKEND		mips_
+#define RELOC_PREFIX	R_MIPS_
+#include "libebl_CPU.h"
+#include "libelfP.h"
+
+#define RELOC_TYPE_ID(type) ((type) & 0xff)
+
+/* 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..5120980c
--- /dev/null
+++ b/backends/mips_reloc.def
@@ -0,0 +1,93 @@ 
+/* List the relocation types for MIPS.  -*- C -*-
+   Copyright (C) 2024 CIP United Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+/*	    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..f2a46495
--- /dev/null
+++ b/backends/mips_symbol.c
@@ -0,0 +1,63 @@ 
+/* MIPS specific symbolic name handling.
+   Copyright (C) 2024 CIP United Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <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_TYPE1(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/libelfP.h b/libelf/libelfP.h
index ed061abb..bdd2cc6a 100644
--- a/libelf/libelfP.h
+++ b/libelf/libelfP.h
@@ -617,4 +617,7 @@  extern void __libelf_reset_rawdata (Elf_Scn *scn, void *buf, size_t size,
 #define INVALID_NDX(ndx, type, data) \
   unlikely ((data)->d_size / sizeof (type) <= (unsigned int) (ndx))
 
+#define ELF64_MIPS_R_TYPE1(i)          ((i) & 0xff)
+#define ELF64_MIPS_R_TYPE2(i)           (((i) >> 8) & 0xff)
+#define ELF64_MIPS_R_TYPE3(i)           (((i) >> 16) & 0xff)
 #endif  /* libelfP.h */
diff --git a/tests/libelf.h b/tests/libelf.h
new file mode 100644
index 00000000..d3f057b4
--- /dev/null
+++ b/tests/libelf.h
@@ -0,0 +1,541 @@ 
+/* Interface for libelf.
+   Copyright (C) 1998-2010, 2015 Red Hat, 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/>.  */
+
+#ifndef _LIBELF_H
+#define _LIBELF_H 1
+
+#include <stdint.h>
+#include <sys/types.h>
+
+/* Get the ELF types.  */
+#include <elf.h>
+
+#ifndef SHF_COMPRESSED
+ /* Older glibc elf.h might not yet define the ELF compression types.  */
+ #define SHF_COMPRESSED      (1 << 11)  /* Section with compressed data. */
+
+ /* Section compression header.  Used when SHF_COMPRESSED is set.  */
+
+ typedef struct
+ {
+   Elf32_Word   ch_type;        /* Compression format.  */
+   Elf32_Word   ch_size;        /* Uncompressed data size.  */
+   Elf32_Word   ch_addralign;   /* Uncompressed data alignment.  */
+ } Elf32_Chdr;
+
+ typedef struct
+ {
+   Elf64_Word   ch_type;        /* Compression format.  */
+   Elf64_Word   ch_reserved;
+   Elf64_Xword  ch_size;        /* Uncompressed data size.  */
+   Elf64_Xword  ch_addralign;   /* Uncompressed data alignment.  */
+ } Elf64_Chdr;
+
+ /* Legal values for ch_type (compression algorithm).  */
+ #define ELFCOMPRESS_ZLIB       1          /* ZLIB/DEFLATE algorithm.  */
+ #define ELFCOMPRESS_LOOS       0x60000000 /* Start of OS-specific.  */
+ #define ELFCOMPRESS_HIOS       0x6fffffff /* End of OS-specific.  */
+ #define ELFCOMPRESS_LOPROC     0x70000000 /* Start of processor-specific.  */
+ #define ELFCOMPRESS_HIPROC     0x7fffffff /* End of processor-specific.  */
+#endif
+
+#ifndef ELFCOMPRESS_ZSTD
+ /* So ZSTD compression can be used even with an old system elf.h.  */
+ #define ELFCOMPRESS_ZSTD       2          /* Zstandard algorithm.  */
+#endif
+
+#ifndef SHT_RELR
+ /* So RELR defines/typedefs can be used even with an old system elf.h.  */
+ #define SHT_RELR       19      /* RELR relative relocations */
+
+ /* RELR relocation table entry */
+ typedef Elf32_Word     Elf32_Relr;
+ typedef Elf64_Xword    Elf64_Relr;
+
+ #define DT_RELRSZ      35      /* Total size of RELR relative relocations */
+ #define DT_RELR        36      /* Address of RELR relative relocations */
+ #define DT_RELRENT     37      /* Size of one RELR relative relocaction */
+#endif
+
+#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)
+# define __nonnull_attribute__(...) __attribute__ ((__nonnull__ (__VA_ARGS__)))
+# define __deprecated_attribute__ __attribute__ ((__deprecated__))
+# define __pure_attribute__ __attribute__ ((__pure__))
+# define __const_attribute__ __attribute__ ((__const__))
+#else
+# define __nonnull_attribute__(...)
+# define __deprecated_attribute__
+# define __pure_attribute__
+# define __const_attribute__
+#endif
+
+#if __GNUC__ < 4
+#define __noreturn_attribute__
+#else
+#define __noreturn_attribute__ __attribute__ ((noreturn))
+#endif
+
+#ifdef __GNUC_STDC_INLINE__
+# define __libdw_extern_inline extern __inline __attribute__ ((__gnu_inline__))
+#else
+# define __libdw_extern_inline extern __inline
+#endif
+
+/* Known translation types.  */
+typedef enum
+{
+  ELF_T_BYTE,                   /* unsigned char */
+  ELF_T_ADDR,                   /* Elf32_Addr, Elf64_Addr, ... */
+  ELF_T_DYN,                    /* Dynamic section record.  */
+  ELF_T_EHDR,                   /* ELF header.  */
+  ELF_T_HALF,                   /* Elf32_Half, Elf64_Half, ... */
+  ELF_T_OFF,                    /* Elf32_Off, Elf64_Off, ... */
+  ELF_T_PHDR,                   /* Program header.  */
+  ELF_T_RELA,                   /* Relocation entry with addend.  */
+  ELF_T_REL,                    /* Relocation entry.  */
+  ELF_T_SHDR,                   /* Section header.  */
+  ELF_T_SWORD,                  /* Elf32_Sword, Elf64_Sword, ... */
+  ELF_T_SYM,                    /* Symbol record.  */
+  ELF_T_WORD,                   /* Elf32_Word, Elf64_Word, ... */
+  ELF_T_XWORD,                  /* Elf32_Xword, Elf64_Xword, ... */
+  ELF_T_SXWORD,                 /* Elf32_Sxword, Elf64_Sxword, ... */
+  ELF_T_VDEF,                   /* Elf32_Verdef, Elf64_Verdef, ... */
+  ELF_T_VDAUX,                  /* Elf32_Verdaux, Elf64_Verdaux, ... */
+  ELF_T_VNEED,                  /* Elf32_Verneed, Elf64_Verneed, ... */
+  ELF_T_VNAUX,                  /* Elf32_Vernaux, Elf64_Vernaux, ... */
+  ELF_T_NHDR,                   /* Elf32_Nhdr, Elf64_Nhdr, ... */
+  ELF_T_SYMINFO,		/* Elf32_Syminfo, Elf64_Syminfo, ... */
+  ELF_T_MOVE,			/* Elf32_Move, Elf64_Move, ... */
+  ELF_T_LIB,			/* Elf32_Lib, Elf64_Lib, ... */
+  ELF_T_GNUHASH,		/* GNU-style hash section.  */
+  ELF_T_AUXV,			/* Elf32_auxv_t, Elf64_auxv_t, ... */
+  ELF_T_CHDR,			/* Compressed, Elf32_Chdr, Elf64_Chdr, ... */
+  ELF_T_NHDR8,			/* Special GNU Properties note.  Same as Nhdr,
+				   except padding.  */
+  ELF_T_RELR,			/* Relative relocation entry.  */
+  /* Keep this the last entry.  */
+  ELF_T_NUM
+} Elf_Type;
+
+/* Descriptor for data to be converted to or from memory format.  */
+typedef struct
+{
+  void *d_buf;			/* Pointer to the actual data.  */
+  Elf_Type d_type;		/* Type of this piece of data.  */
+  unsigned int d_version;	/* ELF version.  */
+  size_t d_size;		/* Size in bytes.  */
+  int64_t d_off;		/* Offset into section.  */
+  size_t d_align;		/* Alignment in section.  */
+} Elf_Data;
+
+
+/* Commands for `...'.  */
+typedef enum
+{
+  ELF_C_NULL,			/* Nothing, terminate, or compute only.  */
+  ELF_C_READ,			/* Read .. */
+  ELF_C_RDWR,			/* Read and write .. */
+  ELF_C_WRITE,			/* Write .. */
+  ELF_C_CLR,			/* Clear flag.  */
+  ELF_C_SET,			/* Set flag.  */
+  ELF_C_FDDONE,			/* Signal that file descriptor will not be
+				   used anymore.  */
+  ELF_C_FDREAD,			/* Read rest of data so that file descriptor
+				   is not used anymore.  */
+  /* The following are extensions.  */
+  ELF_C_READ_MMAP,		/* Read, but mmap the file if possible.  */
+  ELF_C_RDWR_MMAP,		/* Read and write, with mmap.  */
+  ELF_C_WRITE_MMAP,		/* Write, with mmap.  */
+  ELF_C_READ_MMAP_PRIVATE,	/* Read, but memory is writable, results are
+				   not written to the file.  */
+  ELF_C_EMPTY,			/* Copy basic file data but not the content. */
+  /* Keep this the last entry.  */
+  ELF_C_NUM
+} Elf_Cmd;
+
+
+/* Flags for the ELF structures.  */
+enum
+{
+  ELF_F_DIRTY = 0x1,
+#define ELF_F_DIRTY		ELF_F_DIRTY
+  ELF_F_LAYOUT = 0x4,
+#define ELF_F_LAYOUT		ELF_F_LAYOUT
+  ELF_F_PERMISSIVE = 0x8
+#define ELF_F_PERMISSIVE	ELF_F_PERMISSIVE
+};
+
+/* Flags for elf_compress[_gnu].  */
+enum
+{
+  ELF_CHF_FORCE = 0x1
+#define ELF_CHF_FORCE ELF_CHF_FORCE
+};
+
+/* Identification values for recognized object files.  */
+typedef enum
+{
+  ELF_K_NONE,			/* Unknown.  */
+  ELF_K_AR,			/* Archive.  */
+  ELF_K_COFF,			/* Stupid old COFF.  */
+  ELF_K_ELF,			/* ELF file.  */
+  /* Keep this the last entry.  */
+  ELF_K_NUM
+} Elf_Kind;
+
+
+/* Archive member header.  */
+typedef struct
+{
+  char *ar_name;		/* Name of archive member.  */
+  time_t ar_date;		/* File date.  */
+  uid_t ar_uid;			/* User ID.  */
+  gid_t ar_gid;			/* Group ID.  */
+  mode_t ar_mode;		/* File mode.  */
+  int64_t ar_size;		/* File size.  */
+  char *ar_rawname;		/* Original name of archive member.  */
+} Elf_Arhdr;
+
+
+/* Archive symbol table entry.  */
+typedef struct
+{
+  char *as_name;		/* Symbol name.  */
+  size_t as_off;		/* Offset for this file in the archive.  */
+  unsigned long int as_hash;	/* Hash value of the name.  */
+} Elf_Arsym;
+
+
+/* Descriptor for the ELF file.  */
+typedef struct Elf Elf;
+
+/* Descriptor for ELF file section.  */
+typedef struct Elf_Scn Elf_Scn;
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Return descriptor for ELF file to work according to CMD.  */
+extern Elf *elf_begin (int __fildes, Elf_Cmd __cmd, Elf *__ref);
+
+/* Create a clone of an existing ELF descriptor.  */
+  extern Elf *elf_clone (Elf *__elf, Elf_Cmd __cmd);
+
+/* Create descriptor for memory region.  */
+extern Elf *elf_memory (char *__image, size_t __size);
+
+/* Advance archive descriptor to next element.  */
+extern Elf_Cmd elf_next (Elf *__elf);
+
+/* Free resources allocated for ELF.  */
+extern int elf_end (Elf *__elf);
+
+/* Update ELF descriptor and write file to disk.  */
+extern int64_t elf_update (Elf *__elf, Elf_Cmd __cmd);
+
+/* Determine what kind of file is associated with ELF.  */
+extern Elf_Kind elf_kind (Elf *__elf) __pure_attribute__;
+
+/* Get the base offset for an object file.  */
+extern int64_t elf_getbase (Elf *__elf);
+
+
+/* Retrieve file identification data.  */
+extern char *elf_getident (Elf *__elf, size_t *__nbytes);
+
+/* Retrieve class-dependent object file header.  */
+extern Elf32_Ehdr *elf32_getehdr (Elf *__elf);
+/* Similar but this time the binary calls is ELFCLASS64.  */
+extern Elf64_Ehdr *elf64_getehdr (Elf *__elf);
+
+/* Create ELF header if none exists.  */
+extern Elf32_Ehdr *elf32_newehdr (Elf *__elf);
+/* Similar but this time the binary calls is ELFCLASS64.  */
+extern Elf64_Ehdr *elf64_newehdr (Elf *__elf);
+
+/* Get the number of program headers in the ELF file.  If the file uses
+   more headers than can be represented in the e_phnum field of the ELF
+   header the information from the sh_info field in the zeroth section
+   header is used.  */
+extern int elf_getphdrnum (Elf *__elf, size_t *__dst);
+
+/* Retrieve class-dependent program header table.  */
+extern Elf32_Phdr *elf32_getphdr (Elf *__elf);
+/* Similar but this time the binary calls is ELFCLASS64.  */
+extern Elf64_Phdr *elf64_getphdr (Elf *__elf);
+
+/* Create ELF program header.  */
+extern Elf32_Phdr *elf32_newphdr (Elf *__elf, size_t __cnt);
+/* Similar but this time the binary calls is ELFCLASS64.  */
+extern Elf64_Phdr *elf64_newphdr (Elf *__elf, size_t __cnt);
+
+
+/* Get section at INDEX.  */
+extern Elf_Scn *elf_getscn (Elf *__elf, size_t __index);
+
+/* Get section at OFFSET.  */
+extern Elf_Scn *elf32_offscn (Elf *__elf, Elf32_Off __offset);
+/* Similar but this time the binary calls is ELFCLASS64.  */
+extern Elf_Scn *elf64_offscn (Elf *__elf, Elf64_Off __offset);
+
+/* Get index of section.  */
+extern size_t elf_ndxscn (Elf_Scn *__scn);
+
+/* Get section with next section index.  */
+extern Elf_Scn *elf_nextscn (Elf *__elf, Elf_Scn *__scn);
+
+/* Create a new section and append it at the end of the table.  */
+extern Elf_Scn *elf_newscn (Elf *__elf);
+
+/* Get the section index of the extended section index table for the
+   given symbol table.  */
+extern int elf_scnshndx (Elf_Scn *__scn);
+
+/* Get the number of sections in the ELF file.  If the file uses more
+   sections than can be represented in the e_shnum field of the ELF
+   header the information from the sh_size field in the zeroth section
+   header is used.  */
+extern int elf_getshdrnum (Elf *__elf, size_t *__dst);
+/* Sun messed up the implementation of 'elf_getshnum' in their implementation.
+   It was agreed to make the same functionality available under a different
+   name and obsolete the old name.  */
+extern int elf_getshnum (Elf *__elf, size_t *__dst)
+     __deprecated_attribute__;
+
+
+/* Get the section index of the section header string table in the ELF
+   file.  If the index cannot be represented in the e_shstrndx field of
+   the ELF header the information from the sh_link field in the zeroth
+   section header is used.  */
+extern int elf_getshdrstrndx (Elf *__elf, size_t *__dst);
+/* Sun messed up the implementation of 'elf_getshstrndx' in their
+   implementation.  It was agreed to make the same functionality available
+   under a different name and obsolete the old name.  */
+extern int elf_getshstrndx (Elf *__elf, size_t *__dst)
+     __deprecated_attribute__;
+
+
+/* Retrieve section header of ELFCLASS32 binary.  */
+extern Elf32_Shdr *elf32_getshdr (Elf_Scn *__scn);
+/* Similar for ELFCLASS64.  */
+extern Elf64_Shdr *elf64_getshdr (Elf_Scn *__scn);
+
+/* Returns compression header for a section if section data is
+   compressed.  Returns NULL and sets elf_errno if the section isn't
+   compressed or an error occurred.  */
+extern Elf32_Chdr *elf32_getchdr (Elf_Scn *__scn);
+extern Elf64_Chdr *elf64_getchdr (Elf_Scn *__scn);
+
+/* Compress or decompress the data of a section and adjust the section
+   header.
+
+   elf_compress works by setting or clearing the SHF_COMPRESS flag
+   from the section Shdr and will encode or decode a Elf32_Chdr or
+   Elf64_Chdr at the start of the section data.  elf_compress_gnu will
+   encode or decode any section, but is traditionally only used for
+   sections that have a name starting with ".debug" when
+   uncompressed or ".zdebug" when compressed and stores just the
+   uncompressed size.  The GNU compression method is deprecated and
+   should only be used for legacy support.
+
+   elf_compress takes a compression type that should be either zero to
+   decompress or an ELFCOMPRESS algorithm to use for compression.
+   Currently ELFCOMPRESS_ZLIB and ELFCOMPRESS_ZSTD are supported.
+   elf_compress_gnu will compress in the traditional GNU compression
+   format when compress is one and decompress the section data when
+   compress is zero.
+
+   The FLAGS argument can be zero or ELF_CHF_FORCE.  If FLAGS contains
+   ELF_CHF_FORCE then it will always compress the section, even if
+   that would not reduce the size of the data section (including the
+   header).  Otherwise elf_compress and elf_compress_gnu will compress
+   the section only if the total data size is reduced.
+
+   On successful compression or decompression the function returns
+   one.  If (not forced) compression is requested and the data section
+   would not actually reduce in size, the section is not actually
+   compressed and zero is returned.  Otherwise -1 is returned and
+   elf_errno is set.
+
+   It is an error to request compression for a section that already
+   has SHF_COMPRESSED set, or (for elf_compress) to request
+   decompression for an section that doesn't have SHF_COMPRESSED set.
+   If a section has SHF_COMPRESSED set then calling elf_compress_gnu
+   will result in an error.  The section has to be decompressed first
+   using elf_compress.  Calling elf_compress on a section compressed
+   with elf_compress_gnu is fine, but probably useless.
+
+   It is always an error to call these functions on SHT_NOBITS
+   sections or if the section has the SHF_ALLOC flag set.
+   elf_compress_gnu will not check whether the section name starts
+   with ".debug" or .zdebug".  It is the responsibility of the caller
+   to make sure the deprecated GNU compression method is only called
+   on correctly named sections (and to change the name of the section
+   when using elf_compress_gnu).
+
+   All previous returned Shdrs and Elf_Data buffers are invalidated by
+   this call and should no longer be accessed.
+
+   Note that although this changes the header and data returned it
+   doesn't mark the section as dirty.  To keep the changes when
+   calling elf_update the section has to be flagged ELF_F_DIRTY.  */
+extern int elf_compress (Elf_Scn *scn, int type, unsigned int flags);
+extern int elf_compress_gnu (Elf_Scn *scn, int compress, unsigned int flags);
+
+/* Set or clear flags for ELF file.  */
+extern unsigned int elf_flagelf (Elf *__elf, Elf_Cmd __cmd,
+				 unsigned int __flags);
+/* Similarly for the ELF header.  */
+extern unsigned int elf_flagehdr (Elf *__elf, Elf_Cmd __cmd,
+				  unsigned int __flags);
+/* Similarly for the ELF program header.  */
+extern unsigned int elf_flagphdr (Elf *__elf, Elf_Cmd __cmd,
+				  unsigned int __flags);
+/* Similarly for the given ELF section.  */
+extern unsigned int elf_flagscn (Elf_Scn *__scn, Elf_Cmd __cmd,
+				 unsigned int __flags);
+/* Similarly for the given ELF data.  */
+extern unsigned int elf_flagdata (Elf_Data *__data, Elf_Cmd __cmd,
+				  unsigned int __flags);
+/* Similarly for the given ELF section header.  */
+extern unsigned int elf_flagshdr (Elf_Scn *__scn, Elf_Cmd __cmd,
+				  unsigned int __flags);
+
+
+/* Get data from section while translating from file representation to
+   memory representation.  The Elf_Data d_type is set based on the
+   section type if known.  Otherwise d_type is set to ELF_T_BYTE.  If
+   the section contains compressed data then d_type is always set to
+   ELF_T_CHDR.  */
+extern Elf_Data *elf_getdata (Elf_Scn *__scn, Elf_Data *__data);
+
+/* Get uninterpreted section content.  */
+extern Elf_Data *elf_rawdata (Elf_Scn *__scn, Elf_Data *__data);
+
+/* Create new data descriptor for section SCN.  */
+extern Elf_Data *elf_newdata (Elf_Scn *__scn);
+
+/* Get data translated from a chunk of the file contents as section data
+   would be for TYPE.  The resulting Elf_Data pointer is valid until
+   elf_end (ELF) is called.  */
+extern Elf_Data *elf_getdata_rawchunk (Elf *__elf,
+				       int64_t __offset, size_t __size,
+				       Elf_Type __type);
+
+
+/* Return pointer to string at OFFSET in section INDEX.  */
+extern char *elf_strptr (Elf *__elf, size_t __index, size_t __offset);
+
+
+/* Return header of archive.  */
+extern Elf_Arhdr *elf_getarhdr (Elf *__elf);
+
+/* Return offset in archive for current file ELF.  */
+extern int64_t elf_getaroff (Elf *__elf);
+
+/* Select archive element at OFFSET.  */
+extern size_t elf_rand (Elf *__elf, size_t __offset);
+
+/* Get symbol table of archive.  */
+extern Elf_Arsym *elf_getarsym (Elf *__elf, size_t *__narsyms);
+
+
+/* Control ELF descriptor.  */
+extern int elf_cntl (Elf *__elf, Elf_Cmd __cmd);
+
+/* Retrieve uninterpreted file contents.  */
+extern char *elf_rawfile (Elf *__elf, size_t *__nbytes);
+
+
+/* Return size of array of COUNT elements of the type denoted by TYPE
+   in the external representation.  The binary class is taken from ELF.
+   The result is based on version VERSION of the ELF standard.  */
+extern size_t elf32_fsize (Elf_Type __type, size_t __count,
+			   unsigned int __version)
+       __const_attribute__;
+/* Similar but this time the binary calls is ELFCLASS64.  */
+extern size_t elf64_fsize (Elf_Type __type, size_t __count,
+			   unsigned int __version)
+       __const_attribute__;
+
+
+/* Convert data structure from the representation in the file represented
+   by ELF to their memory representation.  */
+extern Elf_Data *elf32_xlatetom (Elf_Data *__dest, const Elf_Data *__src,
+				 unsigned int __encode);
+/* Same for 64 bit class.  */
+extern Elf_Data *elf64_xlatetom (Elf_Data *__dest, const Elf_Data *__src,
+				 unsigned int __encode);
+
+/* Convert data structure from to the representation in memory
+   represented by ELF file representation.  */
+extern Elf_Data *elf32_xlatetof (Elf_Data *__dest, const Elf_Data *__src,
+				 unsigned int __encode);
+/* Same for 64 bit class.  */
+extern Elf_Data *elf64_xlatetof (Elf_Data *__dest, const Elf_Data *__src,
+				 unsigned int __encode);
+
+
+/* Return error code of last failing function call.  This value is kept
+   separately for each thread.  */
+extern int elf_errno (void);
+
+/* Return error string for ERROR.  If ERROR is zero, return error string
+   for most recent error or NULL is none occurred.  If ERROR is -1 the
+   behaviour is similar to the last case except that not NULL but a legal
+   string is returned.  */
+extern const char *elf_errmsg (int __error);
+
+
+/* Coordinate ELF library and application versions.  */
+extern unsigned int elf_version (unsigned int __version);
+
+/* Set fill bytes used to fill holes in data structures.  */
+extern void elf_fill (int __fill);
+
+/* Compute hash value.  */
+extern unsigned long int elf_hash (const char *__string)
+       __pure_attribute__;
+
+/* Compute hash value using the GNU-specific hash function.  */
+extern unsigned long int elf_gnu_hash (const char *__string)
+       __pure_attribute__;
+
+
+/* Compute simple checksum from permanent parts of the ELF file.  */
+extern long int elf32_checksum (Elf *__elf);
+/* Similar but this time the binary calls is ELFCLASS64.  */
+extern long int elf64_checksum (Elf *__elf);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  /* libelf.h */