[v3,3/6] readelf: Adapt src/readelf -h/-S/-r/-w/-l/-d/-a on mips
Commit Message
From: Ying Huang <ying.huang@oss.cipunited.com>
-h: support show Flags name
-S: support show mips related section type
-r: support show type of Relocation section
-w: can work and can show correct "strp" contents
-l: support show mips related program header entry type
-d: can show mips related Dynamic type name
-a: support show complete Object attribute section ".gnu.attributes"
Also add test/run-readelf-reloc.sh file to test new type2/type3 of
src/readelf -r.
Signed-off-by: Ying Huang <ying.huang@oss.cipunited.com>
---
backends/Makefile.am | 2 +-
backends/mips_attrs.c | 140 +++++++++
backends/mips_init.c | 7 +
backends/mips_symbol.c | 571 +++++++++++++++++++++++++++++++++++++
libelf/libelfP.h | 1 +
src/readelf.c | 188 +++++++++---
tests/Makefile.am | 5 +-
tests/run-readelf-reloc.sh | 42 +++
8 files changed, 907 insertions(+), 49 deletions(-)
create mode 100644 backends/mips_attrs.c
create mode 100755 tests/run-readelf-reloc.sh
Comments
Hi Mark,
Could you help review these two patches 3/6 and 4/6, all have been modified according your previous review comments.
If OK, I would update and resubmit again with ChangeLog commit message because there seems to be a conflict in merge now.
Thanks,
Ying
在 2024/3/5 17:51, Ying Huang 写道:
> From: Ying Huang <ying.huang@oss.cipunited.com>
>
> -h: support show Flags name
> -S: support show mips related section type
> -r: support show type of Relocation section
> -w: can work and can show correct "strp" contents
> -l: support show mips related program header entry type
> -d: can show mips related Dynamic type name
> -a: support show complete Object attribute section ".gnu.attributes"
>
> Also add test/run-readelf-reloc.sh file to test new type2/type3 of
> src/readelf -r.
>
> Signed-off-by: Ying Huang <ying.huang@oss.cipunited.com>
> ---
> backends/Makefile.am | 2 +-
> backends/mips_attrs.c | 140 +++++++++
> backends/mips_init.c | 7 +
> backends/mips_symbol.c | 571 +++++++++++++++++++++++++++++++++++++
> libelf/libelfP.h | 1 +
> src/readelf.c | 188 +++++++++---
> tests/Makefile.am | 5 +-
> tests/run-readelf-reloc.sh | 42 +++
> 8 files changed, 907 insertions(+), 49 deletions(-)
> create mode 100644 backends/mips_attrs.c
> create mode 100755 tests/run-readelf-reloc.sh
>
> diff --git a/backends/Makefile.am b/backends/Makefile.am
> index b946fd30..ad95526e 100644
> --- a/backends/Makefile.am
> +++ b/backends/Makefile.am
> @@ -102,7 +102,7 @@ loongarch_SRCS = loongarch_init.c loongarch_symbol.c loongarch_cfi.c \
>
> arc_SRCS = arc_init.c arc_symbol.c
>
> -mips_SRCS = mips_init.c mips_symbol.c
> +mips_SRCS = mips_init.c mips_symbol.c mips_attrs.c
>
> libebl_backends_a_SOURCES = $(i386_SRCS) $(sh_SRCS) $(x86_64_SRCS) \
> $(ia64_SRCS) $(alpha_SRCS) $(arm_SRCS) \
> diff --git a/backends/mips_attrs.c b/backends/mips_attrs.c
> new file mode 100644
> index 00000000..54fd3ce3
> --- /dev/null
> +++ b/backends/mips_attrs.c
> @@ -0,0 +1,140 @@
> +/* Object attribute tags for MIPS.
> + Copyright (C) 2024 CIP United Inc.
> + This file is part of elfutils.
> +
> + This file is free software; you can redistribute it and/or modify
> + it under the terms of either
> +
> + * the GNU Lesser General Public License as published by the Free
> + Software Foundation; either version 3 of the License, or (at
> + your option) any later version
> +
> + or
> +
> + * the GNU General Public License as published by the Free
> + Software Foundation; either version 2 of the License, or (at
> + your option) any later version
> +
> + or both in parallel, as here.
> +
> + elfutils is distributed in the hope that it will be useful, but
> + WITHOUT ANY WARRANTY; without even the implied warranty of
> + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> + General Public License for more details.
> +
> + You should have received copies of the GNU General Public License and
> + the GNU Lesser General Public License along with this program. If
> + not, see <http://www.gnu.org/licenses/>. */
> +
> +#ifdef HAVE_CONFIG_H
> +# include <config.h>
> +#endif
> +
> +#include <string.h>
> +#include <dwarf.h>
> +
> +#define BACKEND mips_
> +#include "libebl_CPU.h"
> +
> +#define KNOWN_VALUES(...) do \
> + { \
> + static const char *table[] = { __VA_ARGS__ }; \
> + if (value < sizeof table / sizeof table[0]) \
> + *value_name = table[value]; \
> + } while (0)
> +
> +//copy gnu attr tags from binutils-2.34/elfcpp/mips.h
> +/* Object attribute tags. */
> +enum
> +{
> + /* 0-3 are generic. */
> +
> + /* Floating-point ABI used by this object file. */
> + Tag_GNU_MIPS_ABI_FP = 4,
> +
> + /* MSA ABI used by this object file. */
> + Tag_GNU_MIPS_ABI_MSA = 8,
> +};
> +
> +/* Object attribute values. */
> +enum
> +{
> + /* Values defined for Tag_GNU_MIPS_ABI_MSA. */
> +
> + /* Not tagged or not using any ABIs affected by the differences. */
> + Val_GNU_MIPS_ABI_MSA_ANY = 0,
> +
> + /* Using 128-bit MSA. */
> + Val_GNU_MIPS_ABI_MSA_128 = 1,
> +};
> +
> +/* Object attribute values. */
> +enum
> +{
> + /* This is reserved for backward-compatibility with an earlier
> + implementation of the MIPS NaN2008 functionality. */
> + Val_GNU_MIPS_ABI_FP_NAN2008 = 8,
> +};
> +
> +/* copy binutils-2.34/binutils/readelf.c display_mips_gnu_attribute */
> +bool
> +mips_check_object_attribute (Ebl *ebl __attribute__ ((unused)),
> + const char *vendor, int tag, uint64_t value,
> + const char **tag_name, const char **value_name)
> +{
> + if (!strcmp (vendor, "gnu"))
> + switch (tag)
> + {
> + case Tag_GNU_MIPS_ABI_FP:
> + *tag_name = "Tag_GNU_MIPS_ABI_FP";
> + switch (value)
> + {
> + case Val_GNU_MIPS_ABI_FP_ANY:
> + *value_name = "Hard or soft float";
> + return true;
> + case Val_GNU_MIPS_ABI_FP_DOUBLE:
> + *value_name = "Hard float (double precision)";
> + return true;
> + case Val_GNU_MIPS_ABI_FP_SINGLE:
> + *value_name = "Hard float (single precision)";
> + return true;
> + case Val_GNU_MIPS_ABI_FP_SOFT:
> + *value_name = "Soft float";
> + return true;
> + case Val_GNU_MIPS_ABI_FP_OLD_64:
> + *value_name = "Hard float (MIPS32r2 64-bit FPU 12 callee-saved)";
> + return true;
> + case Val_GNU_MIPS_ABI_FP_XX:
> + *value_name = "Hard float (32-bit CPU, Any FPU)";
> + return true;
> + case Val_GNU_MIPS_ABI_FP_64:
> + *value_name = "Hard float (32-bit CPU, 64-bit FPU)";
> + return true;
> + case Val_GNU_MIPS_ABI_FP_64A:
> + *value_name = "Hard float compat (32-bit CPU, 64-bit FPU)";
> + return true;
> + case Val_GNU_MIPS_ABI_FP_NAN2008:
> + *value_name = "NaN 2008 compatibility";
> + return true;
> + default:
> + return true;
> + }
> + return true;
> + case Tag_GNU_MIPS_ABI_MSA:
> + *tag_name = "Tag_GNU_MIPS_ABI_MSA";
> + switch (value)
> + {
> + case Val_GNU_MIPS_ABI_MSA_ANY:
> + *value_name = "Any MSA or not";
> + return true;
> + case Val_GNU_MIPS_ABI_MSA_128:
> + *value_name = "128-bit MSA";
> + return true;
> + default:
> + return true;
> + }
> + return true;
> + }
> +
> + return false;
> +}
> diff --git a/backends/mips_init.c b/backends/mips_init.c
> index cedd08ca..6b9bd4c8 100644
> --- a/backends/mips_init.c
> +++ b/backends/mips_init.c
> @@ -48,5 +48,12 @@ mips_init (Elf *elf __attribute__ ((unused)),
> /* We handle it. */
> mips_init_reloc (eh);
> HOOK (eh, reloc_simple_type);
> + HOOK (eh, section_type_name);
> + HOOK (eh, machine_flag_check);
> + HOOK (eh, machine_flag_name);
> + HOOK (eh, segment_type_name);
> + HOOK (eh, dynamic_tag_check);
> + HOOK (eh, dynamic_tag_name);
> + HOOK (eh, check_object_attribute);
> return eh;
> }
> diff --git a/backends/mips_symbol.c b/backends/mips_symbol.c
> index f2a46495..1545fc4b 100644
> --- a/backends/mips_symbol.c
> +++ b/backends/mips_symbol.c
> @@ -61,3 +61,574 @@ mips_reloc_simple_type (Ebl *ebl, int type,
> return ELF_T_NUM;
> }
> }
> +
> +/* copy binutils-2.34/binutils/readelf.c get_mips_section_type_name */
> +const char *
> +mips_section_type_name (int type,
> + char *buf __attribute__ ((unused)),
> + size_t len __attribute__ ((unused)))
> +{
> + switch (type)
> + {
> + case SHT_MIPS_LIBLIST:
> + return "MIPS_LIBLIST";
> + case SHT_MIPS_MSYM:
> + return "MIPS_MSYM";
> + case SHT_MIPS_CONFLICT:
> + return "MIPS_CONFLICT";
> + case SHT_MIPS_GPTAB:
> + return "MIPS_GPTAB";
> + case SHT_MIPS_UCODE:
> + return "MIPS_UCODE";
> + case SHT_MIPS_DEBUG:
> + return "MIPS_DEBUG";
> + case SHT_MIPS_REGINFO:
> + return "MIPS_REGINFO";
> + case SHT_MIPS_PACKAGE:
> + return "MIPS_PACKAGE";
> + case SHT_MIPS_PACKSYM:
> + return "MIPS_PACKSYM";
> + case SHT_MIPS_RELD:
> + return "MIPS_RELD";
> + case SHT_MIPS_IFACE:
> + return "MIPS_IFACE";
> + case SHT_MIPS_CONTENT:
> + return "MIPS_CONTENT";
> + case SHT_MIPS_OPTIONS:
> + return "MIPS_OPTIONS";
> + case SHT_MIPS_SHDR:
> + return "MIPS_SHDR";
> + case SHT_MIPS_FDESC:
> + return "MIPS_FDESC";
> + case SHT_MIPS_EXTSYM:
> + return "MIPS_EXTSYM";
> + case SHT_MIPS_DENSE:
> + return "MIPS_DENSE";
> + case SHT_MIPS_PDESC:
> + return "MIPS_PDESC";
> + case SHT_MIPS_LOCSYM:
> + return "MIPS_LOCSYM";
> + case SHT_MIPS_AUXSYM:
> + return "MIPS_AUXSYM";
> + case SHT_MIPS_OPTSYM:
> + return "MIPS_OPTSYM";
> + case SHT_MIPS_LOCSTR:
> + return "MIPS_LOCSTR";
> + case SHT_MIPS_LINE:
> + return "MIPS_LINE";
> + case SHT_MIPS_RFDESC:
> + return "MIPS_RFDESC";
> + case SHT_MIPS_DELTASYM:
> + return "MIPS_DELTASYM";
> + case SHT_MIPS_DELTAINST:
> + return "MIPS_DELTAINST";
> + case SHT_MIPS_DELTACLASS:
> + return "MIPS_DELTACLASS";
> + case SHT_MIPS_DWARF:
> + return "MIPS_DWARF";
> + case SHT_MIPS_DELTADECL:
> + return "MIPS_DELTADECL";
> + case SHT_MIPS_SYMBOL_LIB:
> + return "MIPS_SYMBOL_LIB";
> + case SHT_MIPS_EVENTS:
> + return "MIPS_EVENTS";
> + case SHT_MIPS_TRANSLATE:
> + return "MIPS_TRANSLATE";
> + case SHT_MIPS_PIXIE:
> + return "MIPS_PIXIE";
> + case SHT_MIPS_XLATE:
> + return "MIPS_XLATE";
> + case SHT_MIPS_XLATE_DEBUG:
> + return "MIPS_XLATE_DEBUG";
> + case SHT_MIPS_WHIRL:
> + return "MIPS_WHIRL";
> + case SHT_MIPS_EH_REGION:
> + return "MIPS_EH_REGION";
> + case SHT_MIPS_XLATE_OLD:
> + return "MIPS_XLATE_OLD";
> + case SHT_MIPS_PDR_EXCEPTION:
> + return "MIPS_PDR_EXCEPTION";
> + case SHT_MIPS_ABIFLAGS:
> + return "MIPS_ABIFLAGS";
> + case SHT_MIPS_XHASH:
> + return "MIPS_XHASH";
> + default:
> + break;
> + }
> + return NULL;
> +}
> +
> +/* Check whether machine flags are valid. */
> +bool
> +mips_machine_flag_check (GElf_Word flags)
> +{
> + if ((flags &~ (EF_MIPS_NOREORDER |
> + EF_MIPS_PIC |
> + EF_MIPS_CPIC |
> + EF_MIPS_UCODE |
> + EF_MIPS_ABI2 |
> + EF_MIPS_OPTIONS_FIRST |
> + EF_MIPS_32BITMODE |
> + EF_MIPS_NAN2008 |
> + EF_MIPS_FP64 |
> + EF_MIPS_ARCH_ASE_MDMX |
> + EF_MIPS_ARCH_ASE_M16 |
> + EF_MIPS_ARCH_ASE_MICROMIPS)) == 0)
> + return false;
> +
> + switch(flags & EF_MIPS_MACH)
> + {
> + case EF_MIPS_MACH_3900:
> + case EF_MIPS_MACH_4010:
> + case EF_MIPS_MACH_4100:
> + case EF_MIPS_MACH_4111:
> + case EF_MIPS_MACH_4120:
> + case EF_MIPS_MACH_4650:
> + case EF_MIPS_MACH_5400:
> + case EF_MIPS_MACH_5500:
> + case EF_MIPS_MACH_5900:
> + case EF_MIPS_MACH_SB1:
> + case EF_MIPS_MACH_9000:
> + case EF_MIPS_MACH_LS2E:
> + case EF_MIPS_MACH_LS2F:
> + case EF_MIPS_MACH_GS464:
> + case EF_MIPS_MACH_GS464E:
> + case EF_MIPS_MACH_GS264E:
> + case EF_MIPS_MACH_OCTEON:
> + case EF_MIPS_MACH_OCTEON2:
> + case EF_MIPS_MACH_OCTEON3:
> + case EF_MIPS_MACH_XLR:
> + case EF_MIPS_MACH_IAMR2:
> + case 0:
> + break;
> + default:
> + return false;
> + }
> +
> + switch ((flags & EF_MIPS_ABI))
> + {
> + case EF_MIPS_ABI_O32:
> + case EF_MIPS_ABI_O64:
> + case EF_MIPS_ABI_EABI32:
> + case EF_MIPS_ABI_EABI64:
> + case 0:
> + break;
> + default:
> + return false;
> + }
> +
> + switch ((flags & EF_MIPS_ARCH))
> + {
> + case EF_MIPS_ARCH_1:
> + case EF_MIPS_ARCH_2:
> + case EF_MIPS_ARCH_3:
> + case EF_MIPS_ARCH_4:
> + case EF_MIPS_ARCH_5:
> + case EF_MIPS_ARCH_32:
> + case EF_MIPS_ARCH_32R2:
> + case EF_MIPS_ARCH_32R6:
> + case EF_MIPS_ARCH_64:
> + case EF_MIPS_ARCH_64R2:
> + case EF_MIPS_ARCH_64R6:
> + return true;
> + default:
> + return false;
> + }
> + return false;
> +}
> +
> +/* copy binutils-2.34/binutils/readelf.c get_machine_flags */
> +const char *
> +mips_machine_flag_name (Elf64_Word orig __attribute__ ((unused)), Elf64_Word *flagref)
> +{
> + if (*flagref & EF_MIPS_NOREORDER)
> + {
> + *flagref &= ~((Elf64_Word) EF_MIPS_NOREORDER);
> + return "noreorder";
> + }
> +
> + if (*flagref & EF_MIPS_PIC)
> + {
> + *flagref &= ~((Elf64_Word) EF_MIPS_PIC);
> + return "pic";
> + }
> +
> + if (*flagref & EF_MIPS_CPIC)
> + {
> + *flagref &= ~((Elf64_Word) EF_MIPS_CPIC);
> + return "cpic";
> + }
> +
> + if (*flagref & EF_MIPS_UCODE)
> + {
> + *flagref &= ~((Elf64_Word) EF_MIPS_UCODE);
> + return "ugen_reserved";
> + }
> +
> + if (*flagref & EF_MIPS_ABI2)
> + {
> + *flagref &= ~((Elf64_Word) EF_MIPS_ABI2);
> + return "abi2";
> + }
> +
> + if (*flagref & EF_MIPS_OPTIONS_FIRST)
> + {
> + *flagref &= ~((Elf64_Word) EF_MIPS_OPTIONS_FIRST);
> + return "odk first";
> + }
> +
> + if (*flagref & EF_MIPS_32BITMODE)
> + {
> + *flagref &= ~((Elf64_Word) EF_MIPS_32BITMODE);
> + return "32bitmode";
> + }
> +
> + if (*flagref & EF_MIPS_NAN2008)
> + {
> + *flagref &= ~((Elf64_Word) EF_MIPS_NAN2008);
> + return "nan2008";
> + }
> +
> + if (*flagref & EF_MIPS_FP64)
> + {
> + *flagref &= ~((Elf64_Word) EF_MIPS_FP64);
> + return "fp64";
> + }
> +
> + switch (*flagref & EF_MIPS_MACH)
> + {
> + case EF_MIPS_MACH_3900:
> + *flagref &= ~((Elf64_Word) EF_MIPS_MACH_3900);
> + return "3900";
> + case EF_MIPS_MACH_4010:
> + *flagref &= ~((Elf64_Word) EF_MIPS_MACH_4010);
> + return "4010";
> + case EF_MIPS_MACH_4100:
> + *flagref &= ~((Elf64_Word) EF_MIPS_MACH_4100);
> + return "4100";
> + case EF_MIPS_MACH_4111:
> + *flagref &= ~((Elf64_Word) EF_MIPS_MACH_4111);
> + return "4111";
> + case EF_MIPS_MACH_4120:
> + *flagref &= ~((Elf64_Word) EF_MIPS_MACH_4120);
> + return "4120";
> + case EF_MIPS_MACH_4650:
> + *flagref &= ~((Elf64_Word) EF_MIPS_MACH_4650);
> + return "4650";
> + case EF_MIPS_MACH_5400:
> + *flagref &= ~((Elf64_Word) EF_MIPS_MACH_5400);
> + return "5400";
> + case EF_MIPS_MACH_5500:
> + *flagref &= ~((Elf64_Word) EF_MIPS_MACH_5500);
> + return "5500";
> + case EF_MIPS_MACH_5900:
> + *flagref &= ~((Elf64_Word) EF_MIPS_MACH_5900);
> + return "5900";
> + case EF_MIPS_MACH_SB1:
> + *flagref &= ~((Elf64_Word) EF_MIPS_MACH_SB1);
> + return "sb1";
> + case EF_MIPS_MACH_9000:
> + *flagref &= ~((Elf64_Word) EF_MIPS_MACH_9000);
> + return "9000";
> + case EF_MIPS_MACH_LS2E:
> + *flagref &= ~((Elf64_Word) EF_MIPS_MACH_LS2E);
> + return "loongson-2e";
> + case EF_MIPS_MACH_LS2F:
> + *flagref &= ~((Elf64_Word) EF_MIPS_MACH_LS2F);
> + return "loongson-2f";
> + case EF_MIPS_MACH_GS464:
> + *flagref &= ~((Elf64_Word) EF_MIPS_MACH_GS464);
> + return "gs464";
> + case EF_MIPS_MACH_GS464E:
> + *flagref &= ~((Elf64_Word) EF_MIPS_MACH_GS464E);
> + return "gs464e";
> + case EF_MIPS_MACH_GS264E:
> + *flagref &= ~((Elf64_Word) EF_MIPS_MACH_GS264E);
> + return "gs264e";
> + case EF_MIPS_MACH_OCTEON:
> + *flagref &= ~((Elf64_Word) EF_MIPS_MACH_OCTEON);
> + return "octeon";
> + case EF_MIPS_MACH_OCTEON2:
> + *flagref &= ~((Elf64_Word) EF_MIPS_MACH_OCTEON2);
> + return "octeon2";
> + case EF_MIPS_MACH_OCTEON3:
> + *flagref &= ~((Elf64_Word) EF_MIPS_MACH_OCTEON3);
> + return "octeon3";
> + case EF_MIPS_MACH_XLR:
> + *flagref &= ~((Elf64_Word) EF_MIPS_MACH_XLR);
> + return "xlr";
> + case EF_MIPS_MACH_IAMR2:
> + *flagref &= ~((Elf64_Word) EF_MIPS_MACH_IAMR2);
> + return "interaptiv-mr2";
> + case 0:
> + /* We simply ignore the field in this case to avoid confusion:
> + MIPS ELF does not specify EF_MIPS_MACH, it is a GNU
> + extension. */
> + break;
> + default:
> + *flagref &= ~((Elf64_Word) EF_MIPS_MACH);
> + return "unknown CPU";
> + }
> + switch (*flagref & EF_MIPS_ABI)
> + {
> + case EF_MIPS_ABI_O32:
> + *flagref &= ~((Elf64_Word) EF_MIPS_ABI_O32);
> + return "o32";
> + case EF_MIPS_ABI_O64:
> + *flagref &= ~((Elf64_Word) EF_MIPS_ABI_O64);
> + return "o64";
> + case EF_MIPS_ABI_EABI32:
> + *flagref &= ~((Elf64_Word) EF_MIPS_ABI_EABI32);
> + return "eabi32";
> + case EF_MIPS_ABI_EABI64:
> + *flagref &= ~((Elf64_Word) EF_MIPS_ABI_EABI64);
> + return "eabi64";
> + case 0:
> + /* We simply ignore the field in this case to avoid confusion:
> + MIPS ELF does not specify EF_MIPS_ABI, it is a GNU extension.
> + This means it is likely to be an o32 file, but not for
> + sure. */
> + break;
> + default:
> + *flagref &= ~((Elf64_Word) EF_MIPS_ABI);
> + return "unknown ABI";
> + }
> +
> + if (*flagref & EF_MIPS_ARCH_ASE_MDMX)
> + {
> + *flagref &= ~((Elf64_Word) EF_MIPS_ARCH_ASE_MDMX);
> + return "mdmx";
> + }
> +
> + if (*flagref & EF_MIPS_ARCH_ASE_M16)
> + {
> + *flagref &= ~((Elf64_Word) EF_MIPS_ARCH_ASE_M16);
> + return "mips16";
> + }
> +
> + if (*flagref & EF_MIPS_ARCH_ASE_MICROMIPS)
> + {
> + *flagref &= ~((Elf64_Word) EF_MIPS_ARCH_ASE_MICROMIPS);
> + return "micromips";
> + }
> +
> + switch (*flagref & EF_MIPS_ARCH)
> + {
> + case EF_MIPS_ARCH_1:
> + *flagref &= ~((Elf64_Word) EF_MIPS_ARCH_1);
> + return "mips1";
> + case EF_MIPS_ARCH_2:
> + *flagref &= ~((Elf64_Word) EF_MIPS_ARCH_2);
> + return "mips2";
> + case EF_MIPS_ARCH_3:
> + *flagref &= ~((Elf64_Word) EF_MIPS_ARCH_3);
> + return "mips3";
> + case EF_MIPS_ARCH_4:
> + *flagref &= ~((Elf64_Word) EF_MIPS_ARCH_4);
> + return "mips4";
> + case EF_MIPS_ARCH_5:
> + *flagref &= ~((Elf64_Word) EF_MIPS_ARCH_5);
> + return "mips5";
> + case EF_MIPS_ARCH_32:
> + *flagref &= ~((Elf64_Word) EF_MIPS_ARCH_32);
> + return "mips32";
> + case EF_MIPS_ARCH_32R2:
> + *flagref &= ~((Elf64_Word) EF_MIPS_ARCH_32R2);
> + return "mips32r2";
> + case EF_MIPS_ARCH_32R6:
> + *flagref &= ~((Elf64_Word) EF_MIPS_ARCH_32R6);
> + return "mips32r6";
> + case EF_MIPS_ARCH_64:
> + *flagref &= ~((Elf64_Word) EF_MIPS_ARCH_64);
> + return "mips64";
> + case EF_MIPS_ARCH_64R2:
> + *flagref &= ~((Elf64_Word) EF_MIPS_ARCH_64R2);
> + return "mips64r2";
> + case EF_MIPS_ARCH_64R6:
> + *flagref &= ~((Elf64_Word) EF_MIPS_ARCH_64R6);
> + return "mips64r6";
> + default:
> + *flagref &= ~((Elf64_Word) EF_MIPS_ARCH);
> + return "unknown ISA";
> + }
> + return NULL;
> +}
> +
> +/* copy binutils-2.34/binutils/readelf.c get_mips_segment_type */
> +const char *
> +mips_segment_type_name (int segment, char *buf __attribute__ ((unused)),
> + size_t len __attribute__ ((unused)))
> +{
> + switch (segment)
> + {
> + case PT_MIPS_REGINFO:
> + return "REGINFO";
> + case PT_MIPS_RTPROC:
> + return "RTPROC";
> + case PT_MIPS_OPTIONS:
> + return "OPTIONS";
> + case PT_MIPS_ABIFLAGS:
> + return "ABIFLAGS";
> + default:
> + return NULL;
> + }
> +}
> +
> +bool
> +mips_dynamic_tag_check (int64_t tag)
> +{
> + return ((tag &~ (DT_MIPS_RLD_VERSION
> + | DT_MIPS_TIME_STAMP
> + | DT_MIPS_ICHECKSUM
> + | DT_MIPS_IVERSION
> + | DT_MIPS_FLAGS
> + | DT_MIPS_BASE_ADDRESS
> + | DT_MIPS_MSYM
> + | DT_MIPS_CONFLICT
> + | DT_MIPS_LIBLIST
> + | DT_MIPS_LOCAL_GOTNO
> + | DT_MIPS_CONFLICTNO
> + | DT_MIPS_LIBLISTNO
> + | DT_MIPS_SYMTABNO
> + | DT_MIPS_UNREFEXTNO
> + | DT_MIPS_GOTSYM
> + | DT_MIPS_HIPAGENO
> + | DT_MIPS_RLD_MAP
> + | DT_MIPS_DELTA_CLASS
> + | DT_MIPS_DELTA_CLASS_NO
> + | DT_MIPS_DELTA_INSTANCE
> + | DT_MIPS_DELTA_INSTANCE_NO
> + | DT_MIPS_DELTA_RELOC
> + | DT_MIPS_DELTA_RELOC_NO
> + | DT_MIPS_DELTA_SYM
> + | DT_MIPS_DELTA_SYM_NO
> + | DT_MIPS_DELTA_CLASSSYM
> + | DT_MIPS_DELTA_CLASSSYM_NO
> + | DT_MIPS_CXX_FLAGS
> + | DT_MIPS_PIXIE_INIT
> + | DT_MIPS_SYMBOL_LIB
> + | DT_MIPS_LOCALPAGE_GOTIDX
> + | DT_MIPS_LOCAL_GOTIDX
> + | DT_MIPS_HIDDEN_GOTIDX
> + | DT_MIPS_PROTECTED_GOTIDX
> + | DT_MIPS_OPTIONS
> + | DT_MIPS_INTERFACE
> + | DT_MIPS_DYNSTR_ALIGN
> + | DT_MIPS_INTERFACE_SIZE
> + | DT_MIPS_RLD_TEXT_RESOLVE_ADDR
> + | DT_MIPS_PERF_SUFFIX
> + | DT_MIPS_COMPACT_SIZE
> + | DT_MIPS_GP_VALUE
> + | DT_MIPS_AUX_DYNAMIC
> + | DT_MIPS_PLTGOT
> + | DT_MIPS_RWPLT
> + | DT_MIPS_RLD_MAP_REL
> + | DT_MIPS_XHASH)) == 0);
> +}
> +
> +/* copy binutils-2.34/binutils/readelf.c get_mips_dynamic_type*/
> +const char *
> +mips_dynamic_tag_name (int64_t tag, char *buf __attribute__ ((unused)),
> + size_t len __attribute__ ((unused)))
> +{
> + switch (tag)
> + {
> + case DT_MIPS_RLD_VERSION:
> + return "MIPS_RLD_VERSION";
> + case DT_MIPS_TIME_STAMP:
> + return "MIPS_TIME_STAMP";
> + case DT_MIPS_ICHECKSUM:
> + return "MIPS_ICHECKSUM";
> + case DT_MIPS_IVERSION:
> + return "MIPS_IVERSION";
> + case DT_MIPS_FLAGS:
> + return "MIPS_FLAGS";
> + case DT_MIPS_BASE_ADDRESS:
> + return "MIPS_BASE_ADDRESS";
> + case DT_MIPS_MSYM:
> + return "MIPS_MSYM";
> + case DT_MIPS_CONFLICT:
> + return "MIPS_CONFLICT";
> + case DT_MIPS_LIBLIST:
> + return "MIPS_LIBLIST";
> + case DT_MIPS_LOCAL_GOTNO:
> + return "MIPS_LOCAL_GOTNO";
> + case DT_MIPS_CONFLICTNO:
> + return "MIPS_CONFLICTNO";
> + case DT_MIPS_LIBLISTNO:
> + return "MIPS_LIBLISTNO";
> + case DT_MIPS_SYMTABNO:
> + return "MIPS_SYMTABNO";
> + case DT_MIPS_UNREFEXTNO:
> + return "MIPS_UNREFEXTNO";
> + case DT_MIPS_GOTSYM:
> + return "MIPS_GOTSYM";
> + case DT_MIPS_HIPAGENO:
> + return "MIPS_HIPAGENO";
> + case DT_MIPS_RLD_MAP:
> + return "MIPS_RLD_MAP";
> + case DT_MIPS_RLD_MAP_REL:
> + return "MIPS_RLD_MAP_REL";
> + case DT_MIPS_DELTA_CLASS:
> + return "MIPS_DELTA_CLASS";
> + case DT_MIPS_DELTA_CLASS_NO:
> + return "MIPS_DELTA_CLASS_NO";
> + case DT_MIPS_DELTA_INSTANCE:
> + return "MIPS_DELTA_INSTANCE";
> + case DT_MIPS_DELTA_INSTANCE_NO:
> + return "MIPS_DELTA_INSTANCE_NO";
> + case DT_MIPS_DELTA_RELOC:
> + return "MIPS_DELTA_RELOC";
> + case DT_MIPS_DELTA_RELOC_NO:
> + return "MIPS_DELTA_RELOC_NO";
> + case DT_MIPS_DELTA_SYM:
> + return "MIPS_DELTA_SYM";
> + case DT_MIPS_DELTA_SYM_NO:
> + return "MIPS_DELTA_SYM_NO";
> + case DT_MIPS_DELTA_CLASSSYM:
> + return "MIPS_DELTA_CLASSSYM";
> + case DT_MIPS_DELTA_CLASSSYM_NO:
> + return "MIPS_DELTA_CLASSSYM_NO";
> + case DT_MIPS_CXX_FLAGS:
> + return "MIPS_CXX_FLAGS";
> + case DT_MIPS_PIXIE_INIT:
> + return "MIPS_PIXIE_INIT";
> + case DT_MIPS_SYMBOL_LIB:
> + return "MIPS_SYMBOL_LIB";
> + case DT_MIPS_LOCALPAGE_GOTIDX:
> + return "MIPS_LOCALPAGE_GOTIDX";
> + case DT_MIPS_LOCAL_GOTIDX:
> + return "MIPS_LOCAL_GOTIDX";
> + case DT_MIPS_HIDDEN_GOTIDX:
> + return "MIPS_HIDDEN_GOTIDX";
> + case DT_MIPS_PROTECTED_GOTIDX:
> + return "MIPS_PROTECTED_GOTIDX";
> + case DT_MIPS_OPTIONS:
> + return "MIPS_OPTIONS";
> + case DT_MIPS_INTERFACE:
> + return "MIPS_INTERFACE";
> + case DT_MIPS_DYNSTR_ALIGN:
> + return "MIPS_DYNSTR_ALIGN";
> + case DT_MIPS_INTERFACE_SIZE:
> + return "MIPS_INTERFACE_SIZE";
> + case DT_MIPS_RLD_TEXT_RESOLVE_ADDR:
> + return "MIPS_RLD_TEXT_RESOLVE_ADDR";
> + case DT_MIPS_PERF_SUFFIX:
> + return "MIPS_PERF_SUFFIX";
> + case DT_MIPS_COMPACT_SIZE:
> + return "MIPS_COMPACT_SIZE";
> + case DT_MIPS_GP_VALUE:
> + return "MIPS_GP_VALUE";
> + case DT_MIPS_AUX_DYNAMIC:
> + return "MIPS_AUX_DYNAMIC";
> + case DT_MIPS_PLTGOT:
> + return "MIPS_PLTGOT";
> + case DT_MIPS_RWPLT:
> + return "MIPS_RWPLT";
> + case DT_MIPS_XHASH:
> + return "MIPS_XHASH";
> + default:
> + return NULL;
> + }
> + return NULL;
> +}
> diff --git a/libelf/libelfP.h b/libelf/libelfP.h
> index bdd2cc6a..6565ee02 100644
> --- a/libelf/libelfP.h
> +++ b/libelf/libelfP.h
> @@ -620,4 +620,5 @@ extern void __libelf_reset_rawdata (Elf_Scn *scn, void *buf, size_t size,
> #define ELF64_MIPS_R_TYPE1(i) ((i) & 0xff)
> #define ELF64_MIPS_R_TYPE2(i) (((i) >> 8) & 0xff)
> #define ELF64_MIPS_R_TYPE3(i) (((i) >> 16) & 0xff)
> +#define is_debug_section_type(type) (type == SHT_PROGBITS || type == SHT_MIPS_DWARF)
> #endif /* libelfP.h */
> diff --git a/src/readelf.c b/src/readelf.c
> index 0e931184..e88cf67c 100644
> --- a/src/readelf.c
> +++ b/src/readelf.c
> @@ -2219,17 +2219,41 @@ handle_relocs_rel (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr)
> (long int) GELF_R_SYM (rel->r_info));
> }
> else if (GELF_ST_TYPE (sym->st_info) != STT_SECTION)
> - printf (" %#0*" PRIx64 " %-20s %#0*" PRIx64 " %s\n",
> - class == ELFCLASS32 ? 10 : 18, rel->r_offset,
> - likely (ebl_reloc_type_check (ebl,
> - GELF_R_TYPE (rel->r_info)))
> - /* Avoid the leading R_ which isn't carrying any
> - information. */
> - ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
> - buf, sizeof (buf)) + 2
> - : _("<INVALID RELOC>"),
> - class == ELFCLASS32 ? 10 : 18, sym->st_value,
> - elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name));
> + {
> + unsigned long inf = rel->r_info;
> + printf (" %#0*" PRIx64 " %-20s %#0*" PRIx64 " %s\n",
> + class == ELFCLASS32 ? 10 : 18, rel->r_offset,
> + likely (ebl_reloc_type_check (ebl,
> + GELF_R_TYPE (rel->r_info)))
> + /* Avoid the leading R_ which isn't carrying any
> + information. */
> + ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
> + buf, sizeof (buf)) + 2
> + : _("<INVALID RELOC>"),
> + class == ELFCLASS32 ? 10 : 18, sym->st_value,
> + elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name));
> +
> + /* copy binutils-2.34/binutils/readelf.c dump_relocations+1753 */
> + if(ebl->elf->class == ELFCLASS64 && ebl->elf->state.elf64.ehdr->e_machine == EM_MIPS)
> + {
> + unsigned int type2 = ELF64_MIPS_R_TYPE2 (inf);
> + unsigned int type3 = ELF64_MIPS_R_TYPE3 (inf);
> + const char * rtype2 = ebl_reloc_type_name (ebl, type2, buf, sizeof (buf)) + 2;
> + const char * rtype3 = ebl_reloc_type_name (ebl, type3, buf, sizeof (buf)) + 2;
> + printf(" Type2: ");
> + if (rtype2 == NULL)
> + printf (_("unrecognized: %lx"), (unsigned long) type2 & 0xffffffff);
> + else
> + printf ("%s", rtype2);
> +
> + printf ("\n Type3: ");
> + if (rtype3 == NULL)
> + printf (_("unrecognized: %lx"), (unsigned long) type3 & 0xffffffff);
> + else
> + printf ("%s", rtype3);
> + printf("\n");
> + }
> + }
> else
> {
> /* This is a relocation against a STT_SECTION symbol. */
> @@ -2253,16 +2277,40 @@ handle_relocs_rel (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr)
> (long int) (sym->st_shndx == SHN_XINDEX
> ? xndx : sym->st_shndx));
> else
> - printf (" %#0*" PRIx64 " %-20s %#0*" PRIx64 " %s\n",
> - class == ELFCLASS32 ? 10 : 18, rel->r_offset,
> - ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
> - /* Avoid the leading R_ which isn't carrying any
> - information. */
> - ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
> - buf, sizeof (buf)) + 2
> - : _("<INVALID RELOC>"),
> - class == ELFCLASS32 ? 10 : 18, sym->st_value,
> - elf_strptr (ebl->elf, shstrndx, secshdr->sh_name));
> + {
> + unsigned long inf = rel->r_info;
> + printf (" %#0*" PRIx64 " %-20s %#0*" PRIx64 " %s\n",
> + class == ELFCLASS32 ? 10 : 18, rel->r_offset,
> + ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
> + /* Avoid the leading R_ which isn't carrying any
> + information. */
> + ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
> + buf, sizeof (buf)) + 2
> + : _("<INVALID RELOC>"),
> + class == ELFCLASS32 ? 10 : 18, sym->st_value,
> + elf_strptr (ebl->elf, shstrndx, secshdr->sh_name));
> +
> + /* copy binutils-2.34/binutils/readelf.c dump_relocations+1753 */
> + if(ebl->elf->class == ELFCLASS64 && ebl->elf->state.elf64.ehdr->e_machine == EM_MIPS)
> + {
> + unsigned int type2 = ELF64_MIPS_R_TYPE2 (inf);
> + unsigned int type3 = ELF64_MIPS_R_TYPE3 (inf);
> + const char * rtype2 = ebl_reloc_type_name (ebl, type2, buf, sizeof (buf)) + 2;
> + const char * rtype3 = ebl_reloc_type_name (ebl, type3, buf, sizeof (buf)) + 2;
> + printf(" Type2: ");
> + if (rtype2 == NULL)
> + printf (_("unrecognized: %lx"), (unsigned long) type2 & 0xffffffff);
> + else
> + printf ("%s", rtype2);
> +
> + printf ("\n Type3: ");
> + if (rtype3 == NULL)
> + printf (_("unrecognized: %lx"), (unsigned long) type3 & 0xffffffff);
> + else
> + printf ("%s", rtype3);
> + printf("\n");
> + }
> + }
> }
> }
> }
> @@ -2410,19 +2458,43 @@ handle_relocs_rela (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr)
> (long int) GELF_R_SYM (rel->r_info));
> }
> else if (GELF_ST_TYPE (sym->st_info) != STT_SECTION)
> - printf ("\
> + {
> + unsigned long inf = rel->r_info;
> + printf ("\
> %#0*" PRIx64 " %-15s %#0*" PRIx64 " %+6" PRId64 " %s\n",
> - class == ELFCLASS32 ? 10 : 18, rel->r_offset,
> - likely (ebl_reloc_type_check (ebl,
> - GELF_R_TYPE (rel->r_info)))
> - /* Avoid the leading R_ which isn't carrying any
> - information. */
> - ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
> - buf, sizeof (buf)) + 2
> - : _("<INVALID RELOC>"),
> - class == ELFCLASS32 ? 10 : 18, sym->st_value,
> - rel->r_addend,
> - elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name));
> + class == ELFCLASS32 ? 10 : 18, rel->r_offset,
> + likely (ebl_reloc_type_check (ebl,
> + GELF_R_TYPE (rel->r_info)))
> + /* Avoid the leading R_ which isn't carrying any
> + information. */
> + ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
> + buf, sizeof (buf)) + 2
> + : _("<INVALID RELOC>"),
> + class == ELFCLASS32 ? 10 : 18, sym->st_value,
> + rel->r_addend,
> + elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name));
> +
> + /* copy binutils-2.34/binutils/readelf.c dump_relocations+1753 */
> + if(ebl->elf->class == ELFCLASS64 && ebl->elf->state.elf64.ehdr->e_machine == EM_MIPS)
> + {
> + unsigned int type2 = ELF64_MIPS_R_TYPE2 (inf);
> + unsigned int type3 = ELF64_MIPS_R_TYPE3 (inf);
> + const char * rtype2 = ebl_reloc_type_name (ebl, type2, buf, sizeof (buf)) + 2;
> + const char * rtype3 = ebl_reloc_type_name (ebl, type3, buf, sizeof (buf)) + 2;
> + printf(" Type2: ");
> + if (rtype2 == NULL)
> + printf (_("unrecognized: %lx"), (unsigned long) type2 & 0xffffffff);
> + else
> + printf ("%s", rtype2);
> +
> + printf ("\n Type3: ");
> + if (rtype3 == NULL)
> + printf (_("unrecognized: %lx"), (unsigned long) type3 & 0xffffffff);
> + else
> + printf ("%s", rtype3);
> + printf("\n");
> + }
> + }
> else
> {
> /* This is a relocation against a STT_SECTION symbol. */
> @@ -2446,18 +2518,42 @@ handle_relocs_rela (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr)
> (long int) (sym->st_shndx == SHN_XINDEX
> ? xndx : sym->st_shndx));
> else
> - printf ("\
> + {
> + unsigned long inf = rel->r_info;
> + printf ("\
> %#0*" PRIx64 " %-15s %#0*" PRIx64 " %+6" PRId64 " %s\n",
> - class == ELFCLASS32 ? 10 : 18, rel->r_offset,
> - ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
> - /* Avoid the leading R_ which isn't carrying any
> - information. */
> - ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
> - buf, sizeof (buf)) + 2
> - : _("<INVALID RELOC>"),
> - class == ELFCLASS32 ? 10 : 18, sym->st_value,
> - rel->r_addend,
> - elf_strptr (ebl->elf, shstrndx, secshdr->sh_name));
> + class == ELFCLASS32 ? 10 : 18, rel->r_offset,
> + ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
> + /* Avoid the leading R_ which isn't carrying any
> + information. */
> + ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
> + buf, sizeof (buf)) + 2
> + : _("<INVALID RELOC>"),
> + class == ELFCLASS32 ? 10 : 18, sym->st_value,
> + rel->r_addend,
> + elf_strptr (ebl->elf, shstrndx, secshdr->sh_name));
> +
> + /* copy binutils-2.34/binutils/readelf.c dump_relocations+1753 */
> + if(ebl->elf->class == ELFCLASS64 && ebl->elf->state.elf64.ehdr->e_machine == EM_MIPS)
> + {
> + unsigned int type2 = ELF64_MIPS_R_TYPE2 (inf);
> + unsigned int type3 = ELF64_MIPS_R_TYPE3 (inf);
> + const char * rtype2 = ebl_reloc_type_name (ebl, type2, buf, sizeof (buf)) + 2;
> + const char * rtype3 = ebl_reloc_type_name (ebl, type3, buf, sizeof (buf)) + 2;
> + printf(" Type2: ");
> + if (rtype2 == NULL)
> + printf (_("unrecognized: %-7lx"), (unsigned long) type2 & 0xffffffff);
> + else
> + printf ("%s", rtype2);
> +
> + printf ("\n Type3: ");
> + if (rtype3 == NULL)
> + printf (_("unrecognized: %lx"), (unsigned long) type3 & 0xffffffff);
> + else
> + printf ("%s", rtype3);
> + printf("\n");
> + }
> + }
> }
> }
> }
> @@ -12043,7 +12139,7 @@ print_debug (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr)
> GElf_Shdr shdr_mem;
> GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
>
> - if (shdr != NULL && shdr->sh_type == SHT_PROGBITS)
> + if (shdr != NULL && is_debug_section_type(shdr->sh_type))
> {
> const char *name = elf_strptr (ebl->elf, shstrndx,
> shdr->sh_name);
> @@ -12073,7 +12169,7 @@ print_debug (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr)
> GElf_Shdr shdr_mem;
> GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
>
> - if (shdr != NULL && shdr->sh_type == SHT_PROGBITS)
> + if (shdr != NULL && is_debug_section_type(shdr->sh_type))
> {
> static const struct
> {
> diff --git a/tests/Makefile.am b/tests/Makefile.am
> index 9141074f..18db4047 100644
> --- a/tests/Makefile.am
> +++ b/tests/Makefile.am
> @@ -214,7 +214,7 @@ TESTS = run-arextract.sh run-arsymtest.sh run-ar.sh newfile test-nlist \
> run-nvidia-extended-linemap-libdw.sh run-nvidia-extended-linemap-readelf.sh \
> run-readelf-dw-form-indirect.sh run-strip-largealign.sh \
> run-readelf-Dd.sh run-dwfl-core-noncontig.sh run-cu-dwp-section-info.sh \
> - run-declfiles.sh
> + run-declfiles.sh run-readelf-reloc.sh
>
> if !BIARCH
> export ELFUTILS_DISABLE_BIARCH = 1
> @@ -646,7 +646,8 @@ EXTRA_DIST = run-arextract.sh run-arsymtest.sh run-ar.sh \
> testfile-dwp-5-cu-index-overflow.dwp.bz2 \
> testfile-dwp-4-cu-index-overflow.bz2 \
> testfile-dwp-4-cu-index-overflow.dwp.bz2 \
> - testfile-dwp-cu-index-overflow.source
> + testfile-dwp-cu-index-overflow.source \
> + run-readelf-reloc.sh
>
>
> if USE_VALGRIND
> diff --git a/tests/run-readelf-reloc.sh b/tests/run-readelf-reloc.sh
> new file mode 100755
> index 00000000..c1a081dd
> --- /dev/null
> +++ b/tests/run-readelf-reloc.sh
> @@ -0,0 +1,42 @@
> +#! /bin/bash
> +# Copyright (C) 2024 CIP United Inc.
> +# This file is part of elfutils.
> +#
> +# This file is free software; you can redistribute it and/or modify
> +# it under the terms of the GNU General Public License as published by
> +# the Free Software Foundation; either version 3 of the License, or
> +# (at your option) any later version.
> +#
> +# elfutils is distributed in the hope that it will be useful, but
> +# WITHOUT ANY WARRANTY; without even the implied warranty of
> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> +# GNU General Public License for more details.
> +#
> +# You should have received a copy of the GNU General Public License
> +# along with this program. If not, see <http://www.gnu.org/licenses/>.
> +
> +. $srcdir/test-subr.sh
> +
> +tempfiles test-readelf-h.txt test-readelf-reloc.txt
> +testrun ${abs_top_builddir}/src/readelf -h ${abs_top_builddir}/src/strip.o > test-readelf-h.txt
> +machine=`cat test-readelf-h.txt | grep Machine`
> +class=`cat test-readelf-h.txt | grep Class`
> +endian=`cat test-readelf-h.txt | grep Data`
> +if [[ "$machine" == *MIPS* && "$class" == *ELF64 && "$endian" == *little* ]]; then
> +testrun ${abs_top_builddir}/src/readelf -r ${abs_top_builddir}/src/strip.o | head -n 12 | tail -n 10 > test-readelf-reloc.txt
> +
> +testrun_compare cat test-readelf-reloc.txt << EOF
> + Offset Type Value Addend Name
> + 0x0000000000000008 MIPS_GPREL16 000000000000000000 +0 .text
> + Type2: MIPS_SUB
> + Type3: MIPS_HI16
> + 0x0000000000000010 MIPS_GPREL16 000000000000000000 +0 .text
> + Type2: MIPS_SUB
> + Type3: MIPS_LO16
> + 0x0000000000000014 MIPS_CALL16 000000000000000000 +0 gelf_getehdr
> + Type2: MIPS_NONE
> + Type3: MIPS_NONE
> +EOF
> +fi
> +
> +exit 0
@@ -102,7 +102,7 @@ loongarch_SRCS = loongarch_init.c loongarch_symbol.c loongarch_cfi.c \
arc_SRCS = arc_init.c arc_symbol.c
-mips_SRCS = mips_init.c mips_symbol.c
+mips_SRCS = mips_init.c mips_symbol.c mips_attrs.c
libebl_backends_a_SOURCES = $(i386_SRCS) $(sh_SRCS) $(x86_64_SRCS) \
$(ia64_SRCS) $(alpha_SRCS) $(arm_SRCS) \
new file mode 100644
@@ -0,0 +1,140 @@
+/* Object attribute tags for MIPS.
+ Copyright (C) 2024 CIP United Inc.
+ This file is part of elfutils.
+
+ This file is free software; you can redistribute it and/or modify
+ it under the terms of either
+
+ * the GNU Lesser General Public License as published by the Free
+ Software Foundation; either version 3 of the License, or (at
+ your option) any later version
+
+ or
+
+ * the GNU General Public License as published by the Free
+ Software Foundation; either version 2 of the License, or (at
+ your option) any later version
+
+ or both in parallel, as here.
+
+ elfutils is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received copies of the GNU General Public License and
+ the GNU Lesser General Public License along with this program. If
+ not, see <http://www.gnu.org/licenses/>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+#include <dwarf.h>
+
+#define BACKEND mips_
+#include "libebl_CPU.h"
+
+#define KNOWN_VALUES(...) do \
+ { \
+ static const char *table[] = { __VA_ARGS__ }; \
+ if (value < sizeof table / sizeof table[0]) \
+ *value_name = table[value]; \
+ } while (0)
+
+//copy gnu attr tags from binutils-2.34/elfcpp/mips.h
+/* Object attribute tags. */
+enum
+{
+ /* 0-3 are generic. */
+
+ /* Floating-point ABI used by this object file. */
+ Tag_GNU_MIPS_ABI_FP = 4,
+
+ /* MSA ABI used by this object file. */
+ Tag_GNU_MIPS_ABI_MSA = 8,
+};
+
+/* Object attribute values. */
+enum
+{
+ /* Values defined for Tag_GNU_MIPS_ABI_MSA. */
+
+ /* Not tagged or not using any ABIs affected by the differences. */
+ Val_GNU_MIPS_ABI_MSA_ANY = 0,
+
+ /* Using 128-bit MSA. */
+ Val_GNU_MIPS_ABI_MSA_128 = 1,
+};
+
+/* Object attribute values. */
+enum
+{
+ /* This is reserved for backward-compatibility with an earlier
+ implementation of the MIPS NaN2008 functionality. */
+ Val_GNU_MIPS_ABI_FP_NAN2008 = 8,
+};
+
+/* copy binutils-2.34/binutils/readelf.c display_mips_gnu_attribute */
+bool
+mips_check_object_attribute (Ebl *ebl __attribute__ ((unused)),
+ const char *vendor, int tag, uint64_t value,
+ const char **tag_name, const char **value_name)
+{
+ if (!strcmp (vendor, "gnu"))
+ switch (tag)
+ {
+ case Tag_GNU_MIPS_ABI_FP:
+ *tag_name = "Tag_GNU_MIPS_ABI_FP";
+ switch (value)
+ {
+ case Val_GNU_MIPS_ABI_FP_ANY:
+ *value_name = "Hard or soft float";
+ return true;
+ case Val_GNU_MIPS_ABI_FP_DOUBLE:
+ *value_name = "Hard float (double precision)";
+ return true;
+ case Val_GNU_MIPS_ABI_FP_SINGLE:
+ *value_name = "Hard float (single precision)";
+ return true;
+ case Val_GNU_MIPS_ABI_FP_SOFT:
+ *value_name = "Soft float";
+ return true;
+ case Val_GNU_MIPS_ABI_FP_OLD_64:
+ *value_name = "Hard float (MIPS32r2 64-bit FPU 12 callee-saved)";
+ return true;
+ case Val_GNU_MIPS_ABI_FP_XX:
+ *value_name = "Hard float (32-bit CPU, Any FPU)";
+ return true;
+ case Val_GNU_MIPS_ABI_FP_64:
+ *value_name = "Hard float (32-bit CPU, 64-bit FPU)";
+ return true;
+ case Val_GNU_MIPS_ABI_FP_64A:
+ *value_name = "Hard float compat (32-bit CPU, 64-bit FPU)";
+ return true;
+ case Val_GNU_MIPS_ABI_FP_NAN2008:
+ *value_name = "NaN 2008 compatibility";
+ return true;
+ default:
+ return true;
+ }
+ return true;
+ case Tag_GNU_MIPS_ABI_MSA:
+ *tag_name = "Tag_GNU_MIPS_ABI_MSA";
+ switch (value)
+ {
+ case Val_GNU_MIPS_ABI_MSA_ANY:
+ *value_name = "Any MSA or not";
+ return true;
+ case Val_GNU_MIPS_ABI_MSA_128:
+ *value_name = "128-bit MSA";
+ return true;
+ default:
+ return true;
+ }
+ return true;
+ }
+
+ return false;
+}
@@ -48,5 +48,12 @@ mips_init (Elf *elf __attribute__ ((unused)),
/* We handle it. */
mips_init_reloc (eh);
HOOK (eh, reloc_simple_type);
+ HOOK (eh, section_type_name);
+ HOOK (eh, machine_flag_check);
+ HOOK (eh, machine_flag_name);
+ HOOK (eh, segment_type_name);
+ HOOK (eh, dynamic_tag_check);
+ HOOK (eh, dynamic_tag_name);
+ HOOK (eh, check_object_attribute);
return eh;
}
@@ -61,3 +61,574 @@ mips_reloc_simple_type (Ebl *ebl, int type,
return ELF_T_NUM;
}
}
+
+/* copy binutils-2.34/binutils/readelf.c get_mips_section_type_name */
+const char *
+mips_section_type_name (int type,
+ char *buf __attribute__ ((unused)),
+ size_t len __attribute__ ((unused)))
+{
+ switch (type)
+ {
+ case SHT_MIPS_LIBLIST:
+ return "MIPS_LIBLIST";
+ case SHT_MIPS_MSYM:
+ return "MIPS_MSYM";
+ case SHT_MIPS_CONFLICT:
+ return "MIPS_CONFLICT";
+ case SHT_MIPS_GPTAB:
+ return "MIPS_GPTAB";
+ case SHT_MIPS_UCODE:
+ return "MIPS_UCODE";
+ case SHT_MIPS_DEBUG:
+ return "MIPS_DEBUG";
+ case SHT_MIPS_REGINFO:
+ return "MIPS_REGINFO";
+ case SHT_MIPS_PACKAGE:
+ return "MIPS_PACKAGE";
+ case SHT_MIPS_PACKSYM:
+ return "MIPS_PACKSYM";
+ case SHT_MIPS_RELD:
+ return "MIPS_RELD";
+ case SHT_MIPS_IFACE:
+ return "MIPS_IFACE";
+ case SHT_MIPS_CONTENT:
+ return "MIPS_CONTENT";
+ case SHT_MIPS_OPTIONS:
+ return "MIPS_OPTIONS";
+ case SHT_MIPS_SHDR:
+ return "MIPS_SHDR";
+ case SHT_MIPS_FDESC:
+ return "MIPS_FDESC";
+ case SHT_MIPS_EXTSYM:
+ return "MIPS_EXTSYM";
+ case SHT_MIPS_DENSE:
+ return "MIPS_DENSE";
+ case SHT_MIPS_PDESC:
+ return "MIPS_PDESC";
+ case SHT_MIPS_LOCSYM:
+ return "MIPS_LOCSYM";
+ case SHT_MIPS_AUXSYM:
+ return "MIPS_AUXSYM";
+ case SHT_MIPS_OPTSYM:
+ return "MIPS_OPTSYM";
+ case SHT_MIPS_LOCSTR:
+ return "MIPS_LOCSTR";
+ case SHT_MIPS_LINE:
+ return "MIPS_LINE";
+ case SHT_MIPS_RFDESC:
+ return "MIPS_RFDESC";
+ case SHT_MIPS_DELTASYM:
+ return "MIPS_DELTASYM";
+ case SHT_MIPS_DELTAINST:
+ return "MIPS_DELTAINST";
+ case SHT_MIPS_DELTACLASS:
+ return "MIPS_DELTACLASS";
+ case SHT_MIPS_DWARF:
+ return "MIPS_DWARF";
+ case SHT_MIPS_DELTADECL:
+ return "MIPS_DELTADECL";
+ case SHT_MIPS_SYMBOL_LIB:
+ return "MIPS_SYMBOL_LIB";
+ case SHT_MIPS_EVENTS:
+ return "MIPS_EVENTS";
+ case SHT_MIPS_TRANSLATE:
+ return "MIPS_TRANSLATE";
+ case SHT_MIPS_PIXIE:
+ return "MIPS_PIXIE";
+ case SHT_MIPS_XLATE:
+ return "MIPS_XLATE";
+ case SHT_MIPS_XLATE_DEBUG:
+ return "MIPS_XLATE_DEBUG";
+ case SHT_MIPS_WHIRL:
+ return "MIPS_WHIRL";
+ case SHT_MIPS_EH_REGION:
+ return "MIPS_EH_REGION";
+ case SHT_MIPS_XLATE_OLD:
+ return "MIPS_XLATE_OLD";
+ case SHT_MIPS_PDR_EXCEPTION:
+ return "MIPS_PDR_EXCEPTION";
+ case SHT_MIPS_ABIFLAGS:
+ return "MIPS_ABIFLAGS";
+ case SHT_MIPS_XHASH:
+ return "MIPS_XHASH";
+ default:
+ break;
+ }
+ return NULL;
+}
+
+/* Check whether machine flags are valid. */
+bool
+mips_machine_flag_check (GElf_Word flags)
+{
+ if ((flags &~ (EF_MIPS_NOREORDER |
+ EF_MIPS_PIC |
+ EF_MIPS_CPIC |
+ EF_MIPS_UCODE |
+ EF_MIPS_ABI2 |
+ EF_MIPS_OPTIONS_FIRST |
+ EF_MIPS_32BITMODE |
+ EF_MIPS_NAN2008 |
+ EF_MIPS_FP64 |
+ EF_MIPS_ARCH_ASE_MDMX |
+ EF_MIPS_ARCH_ASE_M16 |
+ EF_MIPS_ARCH_ASE_MICROMIPS)) == 0)
+ return false;
+
+ switch(flags & EF_MIPS_MACH)
+ {
+ case EF_MIPS_MACH_3900:
+ case EF_MIPS_MACH_4010:
+ case EF_MIPS_MACH_4100:
+ case EF_MIPS_MACH_4111:
+ case EF_MIPS_MACH_4120:
+ case EF_MIPS_MACH_4650:
+ case EF_MIPS_MACH_5400:
+ case EF_MIPS_MACH_5500:
+ case EF_MIPS_MACH_5900:
+ case EF_MIPS_MACH_SB1:
+ case EF_MIPS_MACH_9000:
+ case EF_MIPS_MACH_LS2E:
+ case EF_MIPS_MACH_LS2F:
+ case EF_MIPS_MACH_GS464:
+ case EF_MIPS_MACH_GS464E:
+ case EF_MIPS_MACH_GS264E:
+ case EF_MIPS_MACH_OCTEON:
+ case EF_MIPS_MACH_OCTEON2:
+ case EF_MIPS_MACH_OCTEON3:
+ case EF_MIPS_MACH_XLR:
+ case EF_MIPS_MACH_IAMR2:
+ case 0:
+ break;
+ default:
+ return false;
+ }
+
+ switch ((flags & EF_MIPS_ABI))
+ {
+ case EF_MIPS_ABI_O32:
+ case EF_MIPS_ABI_O64:
+ case EF_MIPS_ABI_EABI32:
+ case EF_MIPS_ABI_EABI64:
+ case 0:
+ break;
+ default:
+ return false;
+ }
+
+ switch ((flags & EF_MIPS_ARCH))
+ {
+ case EF_MIPS_ARCH_1:
+ case EF_MIPS_ARCH_2:
+ case EF_MIPS_ARCH_3:
+ case EF_MIPS_ARCH_4:
+ case EF_MIPS_ARCH_5:
+ case EF_MIPS_ARCH_32:
+ case EF_MIPS_ARCH_32R2:
+ case EF_MIPS_ARCH_32R6:
+ case EF_MIPS_ARCH_64:
+ case EF_MIPS_ARCH_64R2:
+ case EF_MIPS_ARCH_64R6:
+ return true;
+ default:
+ return false;
+ }
+ return false;
+}
+
+/* copy binutils-2.34/binutils/readelf.c get_machine_flags */
+const char *
+mips_machine_flag_name (Elf64_Word orig __attribute__ ((unused)), Elf64_Word *flagref)
+{
+ if (*flagref & EF_MIPS_NOREORDER)
+ {
+ *flagref &= ~((Elf64_Word) EF_MIPS_NOREORDER);
+ return "noreorder";
+ }
+
+ if (*flagref & EF_MIPS_PIC)
+ {
+ *flagref &= ~((Elf64_Word) EF_MIPS_PIC);
+ return "pic";
+ }
+
+ if (*flagref & EF_MIPS_CPIC)
+ {
+ *flagref &= ~((Elf64_Word) EF_MIPS_CPIC);
+ return "cpic";
+ }
+
+ if (*flagref & EF_MIPS_UCODE)
+ {
+ *flagref &= ~((Elf64_Word) EF_MIPS_UCODE);
+ return "ugen_reserved";
+ }
+
+ if (*flagref & EF_MIPS_ABI2)
+ {
+ *flagref &= ~((Elf64_Word) EF_MIPS_ABI2);
+ return "abi2";
+ }
+
+ if (*flagref & EF_MIPS_OPTIONS_FIRST)
+ {
+ *flagref &= ~((Elf64_Word) EF_MIPS_OPTIONS_FIRST);
+ return "odk first";
+ }
+
+ if (*flagref & EF_MIPS_32BITMODE)
+ {
+ *flagref &= ~((Elf64_Word) EF_MIPS_32BITMODE);
+ return "32bitmode";
+ }
+
+ if (*flagref & EF_MIPS_NAN2008)
+ {
+ *flagref &= ~((Elf64_Word) EF_MIPS_NAN2008);
+ return "nan2008";
+ }
+
+ if (*flagref & EF_MIPS_FP64)
+ {
+ *flagref &= ~((Elf64_Word) EF_MIPS_FP64);
+ return "fp64";
+ }
+
+ switch (*flagref & EF_MIPS_MACH)
+ {
+ case EF_MIPS_MACH_3900:
+ *flagref &= ~((Elf64_Word) EF_MIPS_MACH_3900);
+ return "3900";
+ case EF_MIPS_MACH_4010:
+ *flagref &= ~((Elf64_Word) EF_MIPS_MACH_4010);
+ return "4010";
+ case EF_MIPS_MACH_4100:
+ *flagref &= ~((Elf64_Word) EF_MIPS_MACH_4100);
+ return "4100";
+ case EF_MIPS_MACH_4111:
+ *flagref &= ~((Elf64_Word) EF_MIPS_MACH_4111);
+ return "4111";
+ case EF_MIPS_MACH_4120:
+ *flagref &= ~((Elf64_Word) EF_MIPS_MACH_4120);
+ return "4120";
+ case EF_MIPS_MACH_4650:
+ *flagref &= ~((Elf64_Word) EF_MIPS_MACH_4650);
+ return "4650";
+ case EF_MIPS_MACH_5400:
+ *flagref &= ~((Elf64_Word) EF_MIPS_MACH_5400);
+ return "5400";
+ case EF_MIPS_MACH_5500:
+ *flagref &= ~((Elf64_Word) EF_MIPS_MACH_5500);
+ return "5500";
+ case EF_MIPS_MACH_5900:
+ *flagref &= ~((Elf64_Word) EF_MIPS_MACH_5900);
+ return "5900";
+ case EF_MIPS_MACH_SB1:
+ *flagref &= ~((Elf64_Word) EF_MIPS_MACH_SB1);
+ return "sb1";
+ case EF_MIPS_MACH_9000:
+ *flagref &= ~((Elf64_Word) EF_MIPS_MACH_9000);
+ return "9000";
+ case EF_MIPS_MACH_LS2E:
+ *flagref &= ~((Elf64_Word) EF_MIPS_MACH_LS2E);
+ return "loongson-2e";
+ case EF_MIPS_MACH_LS2F:
+ *flagref &= ~((Elf64_Word) EF_MIPS_MACH_LS2F);
+ return "loongson-2f";
+ case EF_MIPS_MACH_GS464:
+ *flagref &= ~((Elf64_Word) EF_MIPS_MACH_GS464);
+ return "gs464";
+ case EF_MIPS_MACH_GS464E:
+ *flagref &= ~((Elf64_Word) EF_MIPS_MACH_GS464E);
+ return "gs464e";
+ case EF_MIPS_MACH_GS264E:
+ *flagref &= ~((Elf64_Word) EF_MIPS_MACH_GS264E);
+ return "gs264e";
+ case EF_MIPS_MACH_OCTEON:
+ *flagref &= ~((Elf64_Word) EF_MIPS_MACH_OCTEON);
+ return "octeon";
+ case EF_MIPS_MACH_OCTEON2:
+ *flagref &= ~((Elf64_Word) EF_MIPS_MACH_OCTEON2);
+ return "octeon2";
+ case EF_MIPS_MACH_OCTEON3:
+ *flagref &= ~((Elf64_Word) EF_MIPS_MACH_OCTEON3);
+ return "octeon3";
+ case EF_MIPS_MACH_XLR:
+ *flagref &= ~((Elf64_Word) EF_MIPS_MACH_XLR);
+ return "xlr";
+ case EF_MIPS_MACH_IAMR2:
+ *flagref &= ~((Elf64_Word) EF_MIPS_MACH_IAMR2);
+ return "interaptiv-mr2";
+ case 0:
+ /* We simply ignore the field in this case to avoid confusion:
+ MIPS ELF does not specify EF_MIPS_MACH, it is a GNU
+ extension. */
+ break;
+ default:
+ *flagref &= ~((Elf64_Word) EF_MIPS_MACH);
+ return "unknown CPU";
+ }
+ switch (*flagref & EF_MIPS_ABI)
+ {
+ case EF_MIPS_ABI_O32:
+ *flagref &= ~((Elf64_Word) EF_MIPS_ABI_O32);
+ return "o32";
+ case EF_MIPS_ABI_O64:
+ *flagref &= ~((Elf64_Word) EF_MIPS_ABI_O64);
+ return "o64";
+ case EF_MIPS_ABI_EABI32:
+ *flagref &= ~((Elf64_Word) EF_MIPS_ABI_EABI32);
+ return "eabi32";
+ case EF_MIPS_ABI_EABI64:
+ *flagref &= ~((Elf64_Word) EF_MIPS_ABI_EABI64);
+ return "eabi64";
+ case 0:
+ /* We simply ignore the field in this case to avoid confusion:
+ MIPS ELF does not specify EF_MIPS_ABI, it is a GNU extension.
+ This means it is likely to be an o32 file, but not for
+ sure. */
+ break;
+ default:
+ *flagref &= ~((Elf64_Word) EF_MIPS_ABI);
+ return "unknown ABI";
+ }
+
+ if (*flagref & EF_MIPS_ARCH_ASE_MDMX)
+ {
+ *flagref &= ~((Elf64_Word) EF_MIPS_ARCH_ASE_MDMX);
+ return "mdmx";
+ }
+
+ if (*flagref & EF_MIPS_ARCH_ASE_M16)
+ {
+ *flagref &= ~((Elf64_Word) EF_MIPS_ARCH_ASE_M16);
+ return "mips16";
+ }
+
+ if (*flagref & EF_MIPS_ARCH_ASE_MICROMIPS)
+ {
+ *flagref &= ~((Elf64_Word) EF_MIPS_ARCH_ASE_MICROMIPS);
+ return "micromips";
+ }
+
+ switch (*flagref & EF_MIPS_ARCH)
+ {
+ case EF_MIPS_ARCH_1:
+ *flagref &= ~((Elf64_Word) EF_MIPS_ARCH_1);
+ return "mips1";
+ case EF_MIPS_ARCH_2:
+ *flagref &= ~((Elf64_Word) EF_MIPS_ARCH_2);
+ return "mips2";
+ case EF_MIPS_ARCH_3:
+ *flagref &= ~((Elf64_Word) EF_MIPS_ARCH_3);
+ return "mips3";
+ case EF_MIPS_ARCH_4:
+ *flagref &= ~((Elf64_Word) EF_MIPS_ARCH_4);
+ return "mips4";
+ case EF_MIPS_ARCH_5:
+ *flagref &= ~((Elf64_Word) EF_MIPS_ARCH_5);
+ return "mips5";
+ case EF_MIPS_ARCH_32:
+ *flagref &= ~((Elf64_Word) EF_MIPS_ARCH_32);
+ return "mips32";
+ case EF_MIPS_ARCH_32R2:
+ *flagref &= ~((Elf64_Word) EF_MIPS_ARCH_32R2);
+ return "mips32r2";
+ case EF_MIPS_ARCH_32R6:
+ *flagref &= ~((Elf64_Word) EF_MIPS_ARCH_32R6);
+ return "mips32r6";
+ case EF_MIPS_ARCH_64:
+ *flagref &= ~((Elf64_Word) EF_MIPS_ARCH_64);
+ return "mips64";
+ case EF_MIPS_ARCH_64R2:
+ *flagref &= ~((Elf64_Word) EF_MIPS_ARCH_64R2);
+ return "mips64r2";
+ case EF_MIPS_ARCH_64R6:
+ *flagref &= ~((Elf64_Word) EF_MIPS_ARCH_64R6);
+ return "mips64r6";
+ default:
+ *flagref &= ~((Elf64_Word) EF_MIPS_ARCH);
+ return "unknown ISA";
+ }
+ return NULL;
+}
+
+/* copy binutils-2.34/binutils/readelf.c get_mips_segment_type */
+const char *
+mips_segment_type_name (int segment, char *buf __attribute__ ((unused)),
+ size_t len __attribute__ ((unused)))
+{
+ switch (segment)
+ {
+ case PT_MIPS_REGINFO:
+ return "REGINFO";
+ case PT_MIPS_RTPROC:
+ return "RTPROC";
+ case PT_MIPS_OPTIONS:
+ return "OPTIONS";
+ case PT_MIPS_ABIFLAGS:
+ return "ABIFLAGS";
+ default:
+ return NULL;
+ }
+}
+
+bool
+mips_dynamic_tag_check (int64_t tag)
+{
+ return ((tag &~ (DT_MIPS_RLD_VERSION
+ | DT_MIPS_TIME_STAMP
+ | DT_MIPS_ICHECKSUM
+ | DT_MIPS_IVERSION
+ | DT_MIPS_FLAGS
+ | DT_MIPS_BASE_ADDRESS
+ | DT_MIPS_MSYM
+ | DT_MIPS_CONFLICT
+ | DT_MIPS_LIBLIST
+ | DT_MIPS_LOCAL_GOTNO
+ | DT_MIPS_CONFLICTNO
+ | DT_MIPS_LIBLISTNO
+ | DT_MIPS_SYMTABNO
+ | DT_MIPS_UNREFEXTNO
+ | DT_MIPS_GOTSYM
+ | DT_MIPS_HIPAGENO
+ | DT_MIPS_RLD_MAP
+ | DT_MIPS_DELTA_CLASS
+ | DT_MIPS_DELTA_CLASS_NO
+ | DT_MIPS_DELTA_INSTANCE
+ | DT_MIPS_DELTA_INSTANCE_NO
+ | DT_MIPS_DELTA_RELOC
+ | DT_MIPS_DELTA_RELOC_NO
+ | DT_MIPS_DELTA_SYM
+ | DT_MIPS_DELTA_SYM_NO
+ | DT_MIPS_DELTA_CLASSSYM
+ | DT_MIPS_DELTA_CLASSSYM_NO
+ | DT_MIPS_CXX_FLAGS
+ | DT_MIPS_PIXIE_INIT
+ | DT_MIPS_SYMBOL_LIB
+ | DT_MIPS_LOCALPAGE_GOTIDX
+ | DT_MIPS_LOCAL_GOTIDX
+ | DT_MIPS_HIDDEN_GOTIDX
+ | DT_MIPS_PROTECTED_GOTIDX
+ | DT_MIPS_OPTIONS
+ | DT_MIPS_INTERFACE
+ | DT_MIPS_DYNSTR_ALIGN
+ | DT_MIPS_INTERFACE_SIZE
+ | DT_MIPS_RLD_TEXT_RESOLVE_ADDR
+ | DT_MIPS_PERF_SUFFIX
+ | DT_MIPS_COMPACT_SIZE
+ | DT_MIPS_GP_VALUE
+ | DT_MIPS_AUX_DYNAMIC
+ | DT_MIPS_PLTGOT
+ | DT_MIPS_RWPLT
+ | DT_MIPS_RLD_MAP_REL
+ | DT_MIPS_XHASH)) == 0);
+}
+
+/* copy binutils-2.34/binutils/readelf.c get_mips_dynamic_type*/
+const char *
+mips_dynamic_tag_name (int64_t tag, char *buf __attribute__ ((unused)),
+ size_t len __attribute__ ((unused)))
+{
+ switch (tag)
+ {
+ case DT_MIPS_RLD_VERSION:
+ return "MIPS_RLD_VERSION";
+ case DT_MIPS_TIME_STAMP:
+ return "MIPS_TIME_STAMP";
+ case DT_MIPS_ICHECKSUM:
+ return "MIPS_ICHECKSUM";
+ case DT_MIPS_IVERSION:
+ return "MIPS_IVERSION";
+ case DT_MIPS_FLAGS:
+ return "MIPS_FLAGS";
+ case DT_MIPS_BASE_ADDRESS:
+ return "MIPS_BASE_ADDRESS";
+ case DT_MIPS_MSYM:
+ return "MIPS_MSYM";
+ case DT_MIPS_CONFLICT:
+ return "MIPS_CONFLICT";
+ case DT_MIPS_LIBLIST:
+ return "MIPS_LIBLIST";
+ case DT_MIPS_LOCAL_GOTNO:
+ return "MIPS_LOCAL_GOTNO";
+ case DT_MIPS_CONFLICTNO:
+ return "MIPS_CONFLICTNO";
+ case DT_MIPS_LIBLISTNO:
+ return "MIPS_LIBLISTNO";
+ case DT_MIPS_SYMTABNO:
+ return "MIPS_SYMTABNO";
+ case DT_MIPS_UNREFEXTNO:
+ return "MIPS_UNREFEXTNO";
+ case DT_MIPS_GOTSYM:
+ return "MIPS_GOTSYM";
+ case DT_MIPS_HIPAGENO:
+ return "MIPS_HIPAGENO";
+ case DT_MIPS_RLD_MAP:
+ return "MIPS_RLD_MAP";
+ case DT_MIPS_RLD_MAP_REL:
+ return "MIPS_RLD_MAP_REL";
+ case DT_MIPS_DELTA_CLASS:
+ return "MIPS_DELTA_CLASS";
+ case DT_MIPS_DELTA_CLASS_NO:
+ return "MIPS_DELTA_CLASS_NO";
+ case DT_MIPS_DELTA_INSTANCE:
+ return "MIPS_DELTA_INSTANCE";
+ case DT_MIPS_DELTA_INSTANCE_NO:
+ return "MIPS_DELTA_INSTANCE_NO";
+ case DT_MIPS_DELTA_RELOC:
+ return "MIPS_DELTA_RELOC";
+ case DT_MIPS_DELTA_RELOC_NO:
+ return "MIPS_DELTA_RELOC_NO";
+ case DT_MIPS_DELTA_SYM:
+ return "MIPS_DELTA_SYM";
+ case DT_MIPS_DELTA_SYM_NO:
+ return "MIPS_DELTA_SYM_NO";
+ case DT_MIPS_DELTA_CLASSSYM:
+ return "MIPS_DELTA_CLASSSYM";
+ case DT_MIPS_DELTA_CLASSSYM_NO:
+ return "MIPS_DELTA_CLASSSYM_NO";
+ case DT_MIPS_CXX_FLAGS:
+ return "MIPS_CXX_FLAGS";
+ case DT_MIPS_PIXIE_INIT:
+ return "MIPS_PIXIE_INIT";
+ case DT_MIPS_SYMBOL_LIB:
+ return "MIPS_SYMBOL_LIB";
+ case DT_MIPS_LOCALPAGE_GOTIDX:
+ return "MIPS_LOCALPAGE_GOTIDX";
+ case DT_MIPS_LOCAL_GOTIDX:
+ return "MIPS_LOCAL_GOTIDX";
+ case DT_MIPS_HIDDEN_GOTIDX:
+ return "MIPS_HIDDEN_GOTIDX";
+ case DT_MIPS_PROTECTED_GOTIDX:
+ return "MIPS_PROTECTED_GOTIDX";
+ case DT_MIPS_OPTIONS:
+ return "MIPS_OPTIONS";
+ case DT_MIPS_INTERFACE:
+ return "MIPS_INTERFACE";
+ case DT_MIPS_DYNSTR_ALIGN:
+ return "MIPS_DYNSTR_ALIGN";
+ case DT_MIPS_INTERFACE_SIZE:
+ return "MIPS_INTERFACE_SIZE";
+ case DT_MIPS_RLD_TEXT_RESOLVE_ADDR:
+ return "MIPS_RLD_TEXT_RESOLVE_ADDR";
+ case DT_MIPS_PERF_SUFFIX:
+ return "MIPS_PERF_SUFFIX";
+ case DT_MIPS_COMPACT_SIZE:
+ return "MIPS_COMPACT_SIZE";
+ case DT_MIPS_GP_VALUE:
+ return "MIPS_GP_VALUE";
+ case DT_MIPS_AUX_DYNAMIC:
+ return "MIPS_AUX_DYNAMIC";
+ case DT_MIPS_PLTGOT:
+ return "MIPS_PLTGOT";
+ case DT_MIPS_RWPLT:
+ return "MIPS_RWPLT";
+ case DT_MIPS_XHASH:
+ return "MIPS_XHASH";
+ default:
+ return NULL;
+ }
+ return NULL;
+}
@@ -620,4 +620,5 @@ extern void __libelf_reset_rawdata (Elf_Scn *scn, void *buf, size_t size,
#define ELF64_MIPS_R_TYPE1(i) ((i) & 0xff)
#define ELF64_MIPS_R_TYPE2(i) (((i) >> 8) & 0xff)
#define ELF64_MIPS_R_TYPE3(i) (((i) >> 16) & 0xff)
+#define is_debug_section_type(type) (type == SHT_PROGBITS || type == SHT_MIPS_DWARF)
#endif /* libelfP.h */
@@ -2219,17 +2219,41 @@ handle_relocs_rel (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr)
(long int) GELF_R_SYM (rel->r_info));
}
else if (GELF_ST_TYPE (sym->st_info) != STT_SECTION)
- printf (" %#0*" PRIx64 " %-20s %#0*" PRIx64 " %s\n",
- class == ELFCLASS32 ? 10 : 18, rel->r_offset,
- likely (ebl_reloc_type_check (ebl,
- GELF_R_TYPE (rel->r_info)))
- /* Avoid the leading R_ which isn't carrying any
- information. */
- ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
- buf, sizeof (buf)) + 2
- : _("<INVALID RELOC>"),
- class == ELFCLASS32 ? 10 : 18, sym->st_value,
- elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name));
+ {
+ unsigned long inf = rel->r_info;
+ printf (" %#0*" PRIx64 " %-20s %#0*" PRIx64 " %s\n",
+ class == ELFCLASS32 ? 10 : 18, rel->r_offset,
+ likely (ebl_reloc_type_check (ebl,
+ GELF_R_TYPE (rel->r_info)))
+ /* Avoid the leading R_ which isn't carrying any
+ information. */
+ ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
+ buf, sizeof (buf)) + 2
+ : _("<INVALID RELOC>"),
+ class == ELFCLASS32 ? 10 : 18, sym->st_value,
+ elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name));
+
+ /* copy binutils-2.34/binutils/readelf.c dump_relocations+1753 */
+ if(ebl->elf->class == ELFCLASS64 && ebl->elf->state.elf64.ehdr->e_machine == EM_MIPS)
+ {
+ unsigned int type2 = ELF64_MIPS_R_TYPE2 (inf);
+ unsigned int type3 = ELF64_MIPS_R_TYPE3 (inf);
+ const char * rtype2 = ebl_reloc_type_name (ebl, type2, buf, sizeof (buf)) + 2;
+ const char * rtype3 = ebl_reloc_type_name (ebl, type3, buf, sizeof (buf)) + 2;
+ printf(" Type2: ");
+ if (rtype2 == NULL)
+ printf (_("unrecognized: %lx"), (unsigned long) type2 & 0xffffffff);
+ else
+ printf ("%s", rtype2);
+
+ printf ("\n Type3: ");
+ if (rtype3 == NULL)
+ printf (_("unrecognized: %lx"), (unsigned long) type3 & 0xffffffff);
+ else
+ printf ("%s", rtype3);
+ printf("\n");
+ }
+ }
else
{
/* This is a relocation against a STT_SECTION symbol. */
@@ -2253,16 +2277,40 @@ handle_relocs_rel (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr)
(long int) (sym->st_shndx == SHN_XINDEX
? xndx : sym->st_shndx));
else
- printf (" %#0*" PRIx64 " %-20s %#0*" PRIx64 " %s\n",
- class == ELFCLASS32 ? 10 : 18, rel->r_offset,
- ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
- /* Avoid the leading R_ which isn't carrying any
- information. */
- ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
- buf, sizeof (buf)) + 2
- : _("<INVALID RELOC>"),
- class == ELFCLASS32 ? 10 : 18, sym->st_value,
- elf_strptr (ebl->elf, shstrndx, secshdr->sh_name));
+ {
+ unsigned long inf = rel->r_info;
+ printf (" %#0*" PRIx64 " %-20s %#0*" PRIx64 " %s\n",
+ class == ELFCLASS32 ? 10 : 18, rel->r_offset,
+ ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
+ /* Avoid the leading R_ which isn't carrying any
+ information. */
+ ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
+ buf, sizeof (buf)) + 2
+ : _("<INVALID RELOC>"),
+ class == ELFCLASS32 ? 10 : 18, sym->st_value,
+ elf_strptr (ebl->elf, shstrndx, secshdr->sh_name));
+
+ /* copy binutils-2.34/binutils/readelf.c dump_relocations+1753 */
+ if(ebl->elf->class == ELFCLASS64 && ebl->elf->state.elf64.ehdr->e_machine == EM_MIPS)
+ {
+ unsigned int type2 = ELF64_MIPS_R_TYPE2 (inf);
+ unsigned int type3 = ELF64_MIPS_R_TYPE3 (inf);
+ const char * rtype2 = ebl_reloc_type_name (ebl, type2, buf, sizeof (buf)) + 2;
+ const char * rtype3 = ebl_reloc_type_name (ebl, type3, buf, sizeof (buf)) + 2;
+ printf(" Type2: ");
+ if (rtype2 == NULL)
+ printf (_("unrecognized: %lx"), (unsigned long) type2 & 0xffffffff);
+ else
+ printf ("%s", rtype2);
+
+ printf ("\n Type3: ");
+ if (rtype3 == NULL)
+ printf (_("unrecognized: %lx"), (unsigned long) type3 & 0xffffffff);
+ else
+ printf ("%s", rtype3);
+ printf("\n");
+ }
+ }
}
}
}
@@ -2410,19 +2458,43 @@ handle_relocs_rela (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr)
(long int) GELF_R_SYM (rel->r_info));
}
else if (GELF_ST_TYPE (sym->st_info) != STT_SECTION)
- printf ("\
+ {
+ unsigned long inf = rel->r_info;
+ printf ("\
%#0*" PRIx64 " %-15s %#0*" PRIx64 " %+6" PRId64 " %s\n",
- class == ELFCLASS32 ? 10 : 18, rel->r_offset,
- likely (ebl_reloc_type_check (ebl,
- GELF_R_TYPE (rel->r_info)))
- /* Avoid the leading R_ which isn't carrying any
- information. */
- ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
- buf, sizeof (buf)) + 2
- : _("<INVALID RELOC>"),
- class == ELFCLASS32 ? 10 : 18, sym->st_value,
- rel->r_addend,
- elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name));
+ class == ELFCLASS32 ? 10 : 18, rel->r_offset,
+ likely (ebl_reloc_type_check (ebl,
+ GELF_R_TYPE (rel->r_info)))
+ /* Avoid the leading R_ which isn't carrying any
+ information. */
+ ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
+ buf, sizeof (buf)) + 2
+ : _("<INVALID RELOC>"),
+ class == ELFCLASS32 ? 10 : 18, sym->st_value,
+ rel->r_addend,
+ elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name));
+
+ /* copy binutils-2.34/binutils/readelf.c dump_relocations+1753 */
+ if(ebl->elf->class == ELFCLASS64 && ebl->elf->state.elf64.ehdr->e_machine == EM_MIPS)
+ {
+ unsigned int type2 = ELF64_MIPS_R_TYPE2 (inf);
+ unsigned int type3 = ELF64_MIPS_R_TYPE3 (inf);
+ const char * rtype2 = ebl_reloc_type_name (ebl, type2, buf, sizeof (buf)) + 2;
+ const char * rtype3 = ebl_reloc_type_name (ebl, type3, buf, sizeof (buf)) + 2;
+ printf(" Type2: ");
+ if (rtype2 == NULL)
+ printf (_("unrecognized: %lx"), (unsigned long) type2 & 0xffffffff);
+ else
+ printf ("%s", rtype2);
+
+ printf ("\n Type3: ");
+ if (rtype3 == NULL)
+ printf (_("unrecognized: %lx"), (unsigned long) type3 & 0xffffffff);
+ else
+ printf ("%s", rtype3);
+ printf("\n");
+ }
+ }
else
{
/* This is a relocation against a STT_SECTION symbol. */
@@ -2446,18 +2518,42 @@ handle_relocs_rela (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr)
(long int) (sym->st_shndx == SHN_XINDEX
? xndx : sym->st_shndx));
else
- printf ("\
+ {
+ unsigned long inf = rel->r_info;
+ printf ("\
%#0*" PRIx64 " %-15s %#0*" PRIx64 " %+6" PRId64 " %s\n",
- class == ELFCLASS32 ? 10 : 18, rel->r_offset,
- ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
- /* Avoid the leading R_ which isn't carrying any
- information. */
- ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
- buf, sizeof (buf)) + 2
- : _("<INVALID RELOC>"),
- class == ELFCLASS32 ? 10 : 18, sym->st_value,
- rel->r_addend,
- elf_strptr (ebl->elf, shstrndx, secshdr->sh_name));
+ class == ELFCLASS32 ? 10 : 18, rel->r_offset,
+ ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
+ /* Avoid the leading R_ which isn't carrying any
+ information. */
+ ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
+ buf, sizeof (buf)) + 2
+ : _("<INVALID RELOC>"),
+ class == ELFCLASS32 ? 10 : 18, sym->st_value,
+ rel->r_addend,
+ elf_strptr (ebl->elf, shstrndx, secshdr->sh_name));
+
+ /* copy binutils-2.34/binutils/readelf.c dump_relocations+1753 */
+ if(ebl->elf->class == ELFCLASS64 && ebl->elf->state.elf64.ehdr->e_machine == EM_MIPS)
+ {
+ unsigned int type2 = ELF64_MIPS_R_TYPE2 (inf);
+ unsigned int type3 = ELF64_MIPS_R_TYPE3 (inf);
+ const char * rtype2 = ebl_reloc_type_name (ebl, type2, buf, sizeof (buf)) + 2;
+ const char * rtype3 = ebl_reloc_type_name (ebl, type3, buf, sizeof (buf)) + 2;
+ printf(" Type2: ");
+ if (rtype2 == NULL)
+ printf (_("unrecognized: %-7lx"), (unsigned long) type2 & 0xffffffff);
+ else
+ printf ("%s", rtype2);
+
+ printf ("\n Type3: ");
+ if (rtype3 == NULL)
+ printf (_("unrecognized: %lx"), (unsigned long) type3 & 0xffffffff);
+ else
+ printf ("%s", rtype3);
+ printf("\n");
+ }
+ }
}
}
}
@@ -12043,7 +12139,7 @@ print_debug (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr)
GElf_Shdr shdr_mem;
GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
- if (shdr != NULL && shdr->sh_type == SHT_PROGBITS)
+ if (shdr != NULL && is_debug_section_type(shdr->sh_type))
{
const char *name = elf_strptr (ebl->elf, shstrndx,
shdr->sh_name);
@@ -12073,7 +12169,7 @@ print_debug (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr)
GElf_Shdr shdr_mem;
GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
- if (shdr != NULL && shdr->sh_type == SHT_PROGBITS)
+ if (shdr != NULL && is_debug_section_type(shdr->sh_type))
{
static const struct
{
@@ -214,7 +214,7 @@ TESTS = run-arextract.sh run-arsymtest.sh run-ar.sh newfile test-nlist \
run-nvidia-extended-linemap-libdw.sh run-nvidia-extended-linemap-readelf.sh \
run-readelf-dw-form-indirect.sh run-strip-largealign.sh \
run-readelf-Dd.sh run-dwfl-core-noncontig.sh run-cu-dwp-section-info.sh \
- run-declfiles.sh
+ run-declfiles.sh run-readelf-reloc.sh
if !BIARCH
export ELFUTILS_DISABLE_BIARCH = 1
@@ -646,7 +646,8 @@ EXTRA_DIST = run-arextract.sh run-arsymtest.sh run-ar.sh \
testfile-dwp-5-cu-index-overflow.dwp.bz2 \
testfile-dwp-4-cu-index-overflow.bz2 \
testfile-dwp-4-cu-index-overflow.dwp.bz2 \
- testfile-dwp-cu-index-overflow.source
+ testfile-dwp-cu-index-overflow.source \
+ run-readelf-reloc.sh
if USE_VALGRIND
new file mode 100755
@@ -0,0 +1,42 @@
+#! /bin/bash
+# Copyright (C) 2024 CIP United Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+tempfiles test-readelf-h.txt test-readelf-reloc.txt
+testrun ${abs_top_builddir}/src/readelf -h ${abs_top_builddir}/src/strip.o > test-readelf-h.txt
+machine=`cat test-readelf-h.txt | grep Machine`
+class=`cat test-readelf-h.txt | grep Class`
+endian=`cat test-readelf-h.txt | grep Data`
+if [[ "$machine" == *MIPS* && "$class" == *ELF64 && "$endian" == *little* ]]; then
+testrun ${abs_top_builddir}/src/readelf -r ${abs_top_builddir}/src/strip.o | head -n 12 | tail -n 10 > test-readelf-reloc.txt
+
+testrun_compare cat test-readelf-reloc.txt << EOF
+ Offset Type Value Addend Name
+ 0x0000000000000008 MIPS_GPREL16 000000000000000000 +0 .text
+ Type2: MIPS_SUB
+ Type3: MIPS_HI16
+ 0x0000000000000010 MIPS_GPREL16 000000000000000000 +0 .text
+ Type2: MIPS_SUB
+ Type3: MIPS_LO16
+ 0x0000000000000014 MIPS_CALL16 000000000000000000 +0 gelf_getehdr
+ Type2: MIPS_NONE
+ Type3: MIPS_NONE
+EOF
+fi
+
+exit 0