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