From patchwork Tue Apr 11 08:12:40 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ying Huang X-Patchwork-Id: 67616 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 2919E385771E for ; Tue, 11 Apr 2023 08:13:10 +0000 (GMT) X-Original-To: elfutils-devel@sourceware.org Delivered-To: elfutils-devel@sourceware.org Received: from s01.bc.larksuite.com (s01.bc.larksuite.com [209.127.230.15]) by sourceware.org (Postfix) with UTF8SMTPS id 191023857019 for ; Tue, 11 Apr 2023 08:12:59 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 191023857019 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=1681200772; h=from:subject:mime-version:from:date:message-id:subject:to:cc: reply-to:content-type:mime-version:in-reply-to:message-id; bh=rbTfXBmXEshY70QXHqKcKeDIXrl6r3iP/AWVHbbEGBc=; b=Nq5VD8SSrrX9gYCioItb1g8ItL9JfGavtqAbWyH4LJ0R6m4MD7K+O5iNpjRSepQI8u/R4Z mA4pIWHm+rvOH5JNlioGv+hhXPSO0JhCXxLd4Vf+dZEbyGMHMnaSgozF6jEtXNWmlIMuF4 W1SSFZuAYG/t/BLkNMxUwKdO90IpdmFK/1ecITkEO9QOSGEP4NkZrxs+iqMQ6HyXGEKwpS Zrelx6v8LySBrB1mRN9x/zpLGyXOe7+3H6Odh3lSEpfy9sFuqKYzcrQ99ZeVeMQKf7W3u9 ltuhmx7USHkV4JrEAZGaayR9e1p7MAmCo8+SKJYnYztYHAxlJ17P3TIwK6eauw== Cc: "Ying Huang" X-Lms-Return-Path: References: <20230411081141.1762395-1-ying.huang@oss.cipunited.com> From: "Ying Huang" Mime-Version: 1.0 Subject: [PATCH 1/5] strip: Adapt src/strip -o -f on mips Message-Id: <20230411081141.1762395-2-ying.huang@oss.cipunited.com> X-Mailer: git-send-email 2.30.2 To: X-Original-From: "Ying Huang" In-Reply-To: <20230411081141.1762395-1-ying.huang@oss.cipunited.com> Date: Tue, 11 Apr 2023 16:12:40 +0800 X-Spam-Status: No, score=-11.2 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 In mips64 little-endian, r_info consists of four byte fields(contains three reloc types) and a 32-bit symbol index. In order to adapt GELF_R_SYM and GELF_R_TYPE, need convert raw data to get correct symbol index and type. libelf/elf_getdata.c: Some eu-utils use read-mmap method to map file, so we need to malloc and memcpy raw data to avoid segment fault. After modification, the correct value are saved in the malloced memory not in process address space. libelf/elf_updata.c: Because we converted the relocation info in mips order when we call elf_getdata.c, so we need to convert the modified data in original order bits before writing the data to the file. --- backends/Makefile.am | 6 ++- backends/mips_init.c | 49 +++++++++++++++++++++ backends/mips_reloc.def | 93 +++++++++++++++++++++++++++++++++++++++ backends/mips_symbol.c | 62 ++++++++++++++++++++++++++ libebl/eblopenbackend.c | 2 + libelf/elf.h | 65 +++++++++++++++++++++++++++- libelf/elf_getdata.c | 96 +++++++++++++++++++++++++++++++++++++++-- libelf/elf_update.c | 53 +++++++++++++++++++++++ 8 files changed, 419 insertions(+), 7 deletions(-) create mode 100644 backends/mips_init.c create mode 100644 backends/mips_reloc.def create mode 100644 backends/mips_symbol.c diff --git a/backends/Makefile.am b/backends/Makefile.am index f373e5fb..bda1b604 100644 --- a/backends/Makefile.am +++ b/backends/Makefile.am @@ -37,7 +37,7 @@ AM_CPPFLAGS += -I$(top_srcdir)/libebl -I$(top_srcdir)/libasm \ noinst_LIBRARIES = libebl_backends.a libebl_backends_pic.a modules = i386 sh x86_64 ia64 alpha arm aarch64 sparc ppc ppc64 s390 \ - m68k bpf riscv csky loongarch arc + m68k bpf riscv csky loongarch arc mips i386_SRCS = i386_init.c i386_symbol.c i386_corenote.c i386_cfi.c \ i386_retval.c i386_regs.c i386_auxv.c \ @@ -100,12 +100,14 @@ loongarch_SRCS = loongarch_init.c loongarch_symbol.c arc_SRCS = arc_init.c arc_symbol.c +mips_SRCS = mips_init.c mips_symbol.c + libebl_backends_a_SOURCES = $(i386_SRCS) $(sh_SRCS) $(x86_64_SRCS) \ $(ia64_SRCS) $(alpha_SRCS) $(arm_SRCS) \ $(aarch64_SRCS) $(sparc_SRCS) $(ppc_SRCS) \ $(ppc64_SRCS) $(s390_SRCS) \ $(m68k_SRCS) $(bpf_SRCS) $(riscv_SRCS) $(csky_SRCS) \ - $(loongarch_SRCS) $(arc_SRCS) + $(loongarch_SRCS) $(arc_SRCS) $(mips_SRCS) libebl_backends_pic_a_SOURCES = am_libebl_backends_pic_a_OBJECTS = $(libebl_backends_a_SOURCES:.c=.os) diff --git a/backends/mips_init.c b/backends/mips_init.c new file mode 100644 index 00000000..f70d62e4 --- /dev/null +++ b/backends/mips_init.c @@ -0,0 +1,49 @@ +/* Initialization of MIPS specific backend library. + Copyright (C) 2023 CIP United Inc. + This file is part of elfutils. + + This file is free software; you can redistribute it and/or modify + it under the terms of either + + * the GNU Lesser General Public License as published by the Free + Software Foundation; either version 3 of the License, or (at + your option) any later version + + or + + * the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at + your option) any later version + + or both in parallel, as here. + + elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received copies of the GNU General Public License and + the GNU Lesser General Public License along with this program. If + not, see . */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#define BACKEND mips_ +#define RELOC_PREFIX R_MIPS_ +#include "libebl_CPU.h" + +/* This defines the common reloc hooks based on mips_reloc.def. */ +#include "common-reloc.c" + +Ebl * +mips_init (Elf *elf __attribute__ ((unused)), + GElf_Half machine __attribute__ ((unused)), + Ebl *eh) +{ + /* We handle it. */ + mips_init_reloc (eh); + HOOK (eh, reloc_simple_type); + return eh; +} diff --git a/backends/mips_reloc.def b/backends/mips_reloc.def new file mode 100644 index 00000000..8cb66a54 --- /dev/null +++ b/backends/mips_reloc.def @@ -0,0 +1,93 @@ +/* List the relocation types for MIPS. -*- C -*- + Copyright (C) 2023 CIP United Inc. + This file is part of elfutils. + + This file is free software; you can redistribute it and/or modify + it under the terms of either + + * the GNU Lesser General Public License as published by the Free + Software Foundation; either version 3 of the License, or (at + your option) any later version + + or + + * the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at + your option) any later version + + or both in parallel, as here. + + elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received copies of the GNU General Public License and + the GNU Lesser General Public License along with this program. If + not, see . */ + +/* NAME, REL|EXEC|DYN */ + + +RELOC_TYPE (NONE, REL|EXEC|DYN) +RELOC_TYPE (16, REL|EXEC|DYN) +RELOC_TYPE (32, REL) +RELOC_TYPE (REL32, REL|EXEC|DYN) +RELOC_TYPE (26, REL|DYN) +RELOC_TYPE (HI16, REL) +RELOC_TYPE (LO16, REL|EXEC|DYN) +RELOC_TYPE (GPREL16, REL|EXEC|DYN) +RELOC_TYPE (LITERAL, REL|EXEC|DYN) +RELOC_TYPE (GOT16, REL|EXEC|DYN) +RELOC_TYPE (PC16, REL) +RELOC_TYPE (CALL16, REL) +RELOC_TYPE (GPREL32, REL) +RELOC_TYPE (SHIFT5, REL) +RELOC_TYPE (SHIFT6, REL) +RELOC_TYPE (64, REL) +RELOC_TYPE (GOT_DISP, REL) +RELOC_TYPE (GOT_PAGE, REL) +RELOC_TYPE (GOT_OFST, REL) +RELOC_TYPE (GOT_HI16, REL) +RELOC_TYPE (GOT_LO16, REL) +RELOC_TYPE (SUB, REL) +RELOC_TYPE (INSERT_A, REL) +RELOC_TYPE (INSERT_B, REL) +RELOC_TYPE (DELETE, REL) +RELOC_TYPE (HIGHER, REL) +RELOC_TYPE (HIGHEST, REL) +RELOC_TYPE (CALL_HI16, REL) +RELOC_TYPE (CALL_LO16, REL) +RELOC_TYPE (SCN_DISP, REL) +RELOC_TYPE (REL16, REL) +RELOC_TYPE (ADD_IMMEDIATE, REL) +RELOC_TYPE (PJUMP, REL) +RELOC_TYPE (RELGOT, REL) +RELOC_TYPE (JALR, REL) +RELOC_TYPE (TLS_DTPMOD32, DYN) +RELOC_TYPE (TLS_DTPREL32, REL) +RELOC_TYPE (TLS_DTPMOD64, DYN) +RELOC_TYPE (TLS_DTPREL64, REL) +RELOC_TYPE (TLS_GD, REL) +RELOC_TYPE (TLS_LDM, REL) +RELOC_TYPE (TLS_DTPREL_HI16, REL) +RELOC_TYPE (TLS_DTPREL_LO16, REL) +RELOC_TYPE (TLS_GOTTPREL, REL) +RELOC_TYPE (TLS_TPREL32, REL) +RELOC_TYPE (TLS_TPREL64, REL) +RELOC_TYPE (TLS_TPREL_HI16, REL) +RELOC_TYPE (TLS_TPREL_LO16, REL) +RELOC_TYPE (GLOB_DAT, REL) +RELOC_TYPE (PC21_S2, REL) +RELOC_TYPE (PC26_S2, REL) +RELOC_TYPE (PC18_S3, REL) +RELOC_TYPE (PC19_S2, REL) +RELOC_TYPE (PCHI16, REL) +RELOC_TYPE (PCLO16, REL) +RELOC_TYPE (COPY, REL) +RELOC_TYPE (JUMP_SLOT, REL) +RELOC_TYPE (PC32, REL) +RELOC_TYPE (EH, REL) +RELOC_TYPE (GNU_REL16_S2, REL) +RELOC_TYPE (GNU_VTINHERIT, REL) +RELOC_TYPE (GNU_VTENTRY, REL) diff --git a/backends/mips_symbol.c b/backends/mips_symbol.c new file mode 100644 index 00000000..4f1bd3e6 --- /dev/null +++ b/backends/mips_symbol.c @@ -0,0 +1,62 @@ +/* MIPS specific symbolic name handling. + Copyright (C) 2023 CIP United Inc. + This file is part of elfutils. + + This file is free software; you can redistribute it and/or modify + it under the terms of either + + * the GNU Lesser General Public License as published by the Free + Software Foundation; either version 3 of the License, or (at + your option) any later version + + or + + * the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at + your option) any later version + + or both in parallel, as here. + + elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received copies of the GNU General Public License and + the GNU Lesser General Public License along with this program. If + not, see . */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +#include +#include +#include +#include +#define BACKEND mips_ +#include "libebl_CPU.h" +#include "libelfP.h" +/* Check for the simple reloc types. */ +Elf_Type +mips_reloc_simple_type (Ebl *ebl, int type, + int *addsub __attribute__ ((unused))) +{ + int typeNew = type; + if(ebl->elf->class == ELFCLASS64) + typeNew = ELF64_MIPS_R_TYPE(type); + switch (typeNew) + { + case R_MIPS_64: + return ELF_T_XWORD; + case R_MIPS_32: + return ELF_T_WORD; + case R_MIPS_16: + return ELF_T_HALF; + + default: + return ELF_T_NUM; + } +} diff --git a/libebl/eblopenbackend.c b/libebl/eblopenbackend.c index 084a1544..a5f7467a 100644 --- a/libebl/eblopenbackend.c +++ b/libebl/eblopenbackend.c @@ -57,6 +57,7 @@ Ebl *riscv_init (Elf *, GElf_Half, Ebl *); Ebl *csky_init (Elf *, GElf_Half, Ebl *); Ebl *loongarch_init (Elf *, GElf_Half, Ebl *); Ebl *arc_init (Elf *, GElf_Half, Ebl *); +Ebl *mips_init (Elf *, GElf_Half, Ebl *); /* This table should contain the complete list of architectures as far as the ELF specification is concerned. */ @@ -154,6 +155,7 @@ static const struct { csky_init, "elf_csky", "csky", 4, EM_CSKY, ELFCLASS32, ELFDATA2LSB }, { loongarch_init, "elf_loongarch", "loongarch", 9, EM_LOONGARCH, ELFCLASS64, ELFDATA2LSB }, { arc_init, "elf_arc", "arc", 3, EM_ARCV2, ELFCLASS32, ELFDATA2LSB }, + { mips_init, "elf_mips", "mips", 4, EM_MIPS, 0, 0 }, }; #define nmachines (sizeof (machines) / sizeof (machines[0])) diff --git a/libelf/elf.h b/libelf/elf.h index 4bc0e429..aa903837 100644 --- a/libelf/elf.h +++ b/libelf/elf.h @@ -678,6 +678,9 @@ typedef Elf64_Xword Elf64_Relr; #define ELF64_R_SYM(i) ((i) >> 32) #define ELF64_R_TYPE(i) ((i) & 0xffffffff) +#define ELF64_MIPS_R_TYPE(i) ((i) & 0xff) +#define ELF64_MIPS_R_TYPE2(i) (((i) >> 8) & 0xff) +#define ELF64_MIPS_R_TYPE3(i) (((i) >> 16) & 0xff) #define ELF64_R_INFO(sym,type) ((((Elf64_Xword) (sym)) << 32) + (type)) /* Program segment header. */ @@ -1927,11 +1930,69 @@ typedef struct #define R_MIPS_TLS_TPREL_HI16 49 /* TP-relative offset, high 16 bits */ #define R_MIPS_TLS_TPREL_LO16 50 /* TP-relative offset, low 16 bits */ #define R_MIPS_GLOB_DAT 51 +#define R_MIPS_PC21_S2 60 +/* copy binutils-2.34/elfcpp/mips.h +102 */ +#define R_MIPS_PC26_S2 61 +#define R_MIPS_PC18_S3 62 +#define R_MIPS_PC19_S2 63 +#define R_MIPS_PCHI16 64 +#define R_MIPS_PCLO16 65 +#define R_MIPS16_26 100 +#define R_MIPS16_GPREL 101 +#define R_MIPS16_GOT16 102 +#define R_MIPS16_CALL16 103 +#define R_MIPS16_HI16 104 +#define R_MIPS16_LO16 105 +#define R_MIPS16_TLS_GD 106 +#define R_MIPS16_TLS_LDM 107 +#define R_MIPS16_TLS_DTPREL_HI16 108 +#define R_MIPS16_TLS_DTPREL_LO16 109 +#define R_MIPS16_TLS_GOTTPREL 110 +#define R_MIPS16_TLS_TPREL_HI16 111 +#define R_MIPS16_TLS_TPREL_LO16 112 +#define R_MIPS16_PC16_S1 113 #define R_MIPS_COPY 126 #define R_MIPS_JUMP_SLOT 127 +#define R_MIPS_RELATIVE 128 +#define R_MICROMIPS_26_S1 133 +#define R_MICROMIPS_HI16 134 +#define R_MICROMIPS_LO16 135 +#define R_MICROMIPS_GPREL16 136 +#define R_MICROMIPS_LITERAL 137 +#define R_MICROMIPS_GOT16 138 +#define R_MICROMIPS_PC7_S1 139 +#define R_MICROMIPS_PC10_S1 140 +#define R_MICROMIPS_PC16_S1 141 +#define R_MICROMIPS_CALL16 142 +#define R_MICROMIPS_GOT_DISP 145 +#define R_MICROMIPS_GOT_PAGE 146 +#define R_MICROMIPS_GOT_OFST 147 +#define R_MICROMIPS_GOT_HI16 148 +#define R_MICROMIPS_GOT_LO16 149 +#define R_MICROMIPS_SUB 150 +#define R_MICROMIPS_HIGHER 151 +#define R_MICROMIPS_HIGHEST 152 +#define R_MICROMIPS_CALL_HI16 153 +#define R_MICROMIPS_CALL_LO16 154 +#define R_MICROMIPS_SCN_DISP 155 +#define R_MICROMIPS_JALR 156 +#define R_MICROMIPS_HI0_LO16 157 +#define R_MICROMIPS_TLS_GD 162 +#define R_MICROMIPS_TLS_LDM 163 +#define R_MICROMIPS_TLS_DTPREL_HI16 164 +#define R_MICROMIPS_TLS_DTPREL_LO16 165 +#define R_MICROMIPS_TLS_GOTTPREL 166 +#define R_MICROMIPS_TLS_TPREL_HI16 169 +#define R_MICROMIPS_TLS_TPREL_LO16 170 +#define R_MICROMIPS_GPREL7_S2 172 +#define R_MICROMIPS_PC23_S2 173 +#define R_MIPS_PC32 248 +#define R_MIPS_EH 249 +#define R_MIPS_GNU_REL16_S2 250 +#define R_MIPS_GNU_VTINHERIT 253 +#define R_MIPS_GNU_VTENTRY 254 /* Keep this the last entry. */ -#define R_MIPS_NUM 128 - +#define R_MIPS_NUM 255 /* Legal values for p_type field of Elf32_Phdr. */ #define PT_MIPS_REGINFO 0x70000000 /* Register usage information. */ diff --git a/libelf/elf_getdata.c b/libelf/elf_getdata.c index 5ebd270f..80f91124 100644 --- a/libelf/elf_getdata.c +++ b/libelf/elf_getdata.c @@ -139,13 +139,38 @@ convert_data (Elf_Scn *scn, int eclass, int data, size_t size, Elf_Type type) { const size_t align = __libelf_type_align (eclass, type); + GElf_Shdr shdr_mem; + GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); + GElf_Ehdr ehdr_mem; + GElf_Ehdr *ehdr = gelf_getehdr (scn->elf, &ehdr_mem); /* Do we need to convert the data and/or adjust for alignment? */ if (data == MY_ELFDATA || type == ELF_T_BYTE) { if (((((size_t) (char *) scn->rawdata_base)) & (align - 1)) == 0) - /* No need to copy, we can use the raw data. */ - scn->data_base = scn->rawdata_base; + { + /* In order to adapt macro GELF_R_SYM and GELF_R_TYPE on mips64, need to convert + relocation info(raw data). Some eu-utils use read-mmap method to map file, so + we need to malloc and memcpy raw data to avoid segment fault. After modification, + the correct value are saved in the malloced memory not in process address space. */ + if (shdr != NULL && (shdr->sh_type == SHT_RELA || shdr->sh_type == SHT_REL) && + scn->elf->class == ELFCLASS64 && ehdr != NULL && + ehdr->e_machine == EM_MIPS && ehdr->e_ident[EI_DATA] == ELFDATA2LSB) + { + scn->data_base = malloc (size); + if (scn->data_base == NULL) + { + __libelf_seterrno (ELF_E_NOMEM); + return; + } + + /* The copy will be appropriately aligned for direct access. */ + memcpy (scn->data_base, scn->rawdata_base, size); + } + else + /* No need to copy, we can use the raw data. */ + scn->data_base = scn->rawdata_base; + } else { scn->data_base = malloc (size); @@ -174,7 +199,28 @@ convert_data (Elf_Scn *scn, int eclass, function to directly access the data elements. */ char *rawdata_source; if (((((size_t) (char *) scn->rawdata_base)) & (align - 1)) == 0) - rawdata_source = scn->rawdata_base; + { + /* In order to adapt macro GELF_R_SYM and GELF_R_TYPE on mips64, need to convert + relocation info(raw data). Some eu-utils use read-mmap method to map file, so + we need to malloc and memcpy raw data to avoid segment fault. After modification, + the correct value are saved in the malloced memory not in process address space. */ + if (shdr != NULL && (shdr->sh_type == SHT_RELA || shdr->sh_type == SHT_REL) && + scn->elf->class == ELFCLASS64 && ehdr != NULL && + ehdr->e_machine == EM_MIPS && ehdr->e_ident[EI_DATA] == ELFDATA2LSB) + { + rawdata_source = malloc (size); + if (rawdata_source == NULL) + { + __libelf_seterrno (ELF_E_NOMEM); + return; + } + + /* The copy will be appropriately aligned for direct access. */ + memcpy (rawdata_source, scn->rawdata_base, size); + } + else + rawdata_source = scn->rawdata_base; + } else { rawdata_source = malloc (size); @@ -205,6 +251,50 @@ convert_data (Elf_Scn *scn, int eclass, scn->data_list.data.d.d_version = scn->rawdata.d.d_version; scn->data_list.data.s = scn; + + /* In mips64 little-endian, r_info consists of four byte fields(contains + three reloc types) and a 32-bit symbol index. In order to adapt + GELF_R_SYM and GELF_R_TYPE, need to convert r_info to get correct symbol + index and type. */ + if (shdr != NULL && (shdr->sh_type == SHT_RELA || shdr->sh_type == SHT_REL) && + scn->elf->class == ELFCLASS64 && + ehdr != NULL && ehdr->e_machine == EM_MIPS && ehdr->e_ident[EI_DATA] == ELFDATA2LSB) + { + if (shdr->sh_type == SHT_REL) + { + size_t sh_entsize = gelf_fsize (scn->elf, ELF_T_REL, 1, EV_CURRENT); + int nentries = shdr->sh_size / sh_entsize; + for (int cnt = 0; cnt < nentries; ++cnt) + { + Elf_Data_Scn *data_scn = (Elf_Data_Scn *) &scn->data_list.data.d; + Elf64_Rel *value = &((Elf64_Rel *) data_scn->d.d_buf)[cnt]; + Elf64_Xword info = value->r_info; + value->r_info = (((info & 0xffffffff) << 32) + | ((info >> 56) & 0xff) + | ((info >> 40) & 0xff00) + | ((info >> 24) & 0xff0000) + | ((info >> 8) & 0xff000000)); + ((Elf64_Rel *) data_scn->d.d_buf)[cnt] = *value; + } + } + else if (shdr->sh_type == SHT_RELA) + { + size_t sh_entsize = gelf_fsize (scn->elf, ELF_T_RELA, 1, EV_CURRENT); + int nentries = shdr->sh_size / sh_entsize; + for (int cnt = 0; cnt < nentries; cnt++) + { + Elf_Data_Scn *data_scn = (Elf_Data_Scn *) &scn->data_list.data.d; + Elf64_Rela *value = &((Elf64_Rela *) data_scn->d.d_buf)[cnt]; + Elf64_Xword info = value->r_info; + value->r_info = (((info & 0xffffffff) << 32) + | ((info >> 56) & 0xff) + | ((info >> 40) & 0xff00) + | ((info >> 24) & 0xff0000) + | ((info >> 8) & 0xff000000)); + ((Elf64_Rela *) data_scn->d.d_buf)[cnt] = *value; + } + } + } } diff --git a/libelf/elf_update.c b/libelf/elf_update.c index 56af3a1c..11027c38 100644 --- a/libelf/elf_update.c +++ b/libelf/elf_update.c @@ -228,7 +228,60 @@ elf_update (Elf *elf, Elf_Cmd cmd) size = -1; } else + { + /* Because we converted the relocation info in mips order when we call elf_getdata.c, + so we need to convert the modified data in original order bits before writing the + data to the file. */ + Elf_Scn *scn = NULL; + while ((scn = elf_nextscn (elf, scn)) != NULL) + { + GElf_Shdr shdr_mem; + GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); + GElf_Ehdr ehdr_mem; + GElf_Ehdr *ehdr = gelf_getehdr (scn->elf, &ehdr_mem); + if (shdr != NULL && (shdr->sh_type == SHT_RELA || shdr->sh_type == SHT_REL) && + scn->elf->class == ELFCLASS64 && + ehdr != NULL && ehdr->e_machine == EM_MIPS && ehdr->e_ident[EI_DATA] == ELFDATA2LSB) + { + Elf_Data *d = elf_getdata (scn, NULL); + if (shdr->sh_type == SHT_REL) + { + size_t sh_entsize = gelf_fsize (scn->elf, ELF_T_REL, 1, EV_CURRENT); + int nentries = shdr->sh_size / sh_entsize; + for (int cnt = 0; cnt < nentries; ++cnt) + { + Elf_Data_Scn *data_scn = (Elf_Data_Scn *) d; + Elf64_Rel *value = &((Elf64_Rel *) data_scn->d.d_buf)[cnt]; + Elf64_Xword info = value->r_info; + value->r_info = (info >> 32 + | ((info << 56) & 0xff00000000000000) + | ((info << 40) & 0xff000000000000) + | ((info << 24) & 0xff0000000000) + | ((info << 8) & 0xff00000000)); + ((Elf64_Rel *) data_scn->d.d_buf)[cnt] = *value; + } + } + else if (shdr->sh_type == SHT_RELA) + { + size_t sh_entsize = gelf_fsize (scn->elf, ELF_T_RELA, 1, EV_CURRENT); + int nentries = shdr->sh_size / sh_entsize; + for (int cnt = 0; cnt < nentries; cnt++) + { + Elf_Data_Scn *data_scn = (Elf_Data_Scn *) d; + Elf64_Rela *value = &((Elf64_Rela *) data_scn->d.d_buf)[cnt]; + Elf64_Xword info = value->r_info; + value->r_info = (info >> 32 + | ((info << 56) & 0xff00000000000000) + | ((info << 40) & 0xff000000000000) + | ((info << 24) & 0xff0000000000) + | ((info << 8) & 0xff00000000)); + ((Elf64_Rela *) data_scn->d.d_buf)[cnt] = *value; + } + } + } + } size = write_file (elf, size, change_bo, shnum); + } } out: 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 { From patchwork Tue Apr 11 08:12:46 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ying Huang X-Patchwork-Id: 67614 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 AA9B43857029 for ; Tue, 11 Apr 2023 08:12:59 +0000 (GMT) X-Original-To: elfutils-devel@sourceware.org Delivered-To: elfutils-devel@sourceware.org Received: from s01.bc.larksuite.com (s01.bc.larksuite.com [209.127.230.13]) by sourceware.org (Postfix) with UTF8SMTPS id 3684C3858002 for ; Tue, 11 Apr 2023 08:12:53 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 3684C3858002 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=1681200766; h=from:subject:mime-version:from:date:message-id:subject:to:cc: reply-to:content-type:mime-version:in-reply-to:message-id; bh=d6onvIp9GAcNWJ4oUuN/PsDp9wDW/TRysVQjN+8umHg=; b=jjKSu9Bom/khQgOjPCyqtajcD9XH2lK/yS/+q7FCD9prYHtqbRaoJc78xpcSOdwE+b0NPu v5991kefLZqtipVmZltmvWRlF6VjP1TwATN1XCof8fTmIWOqTzfZtYPEhZmt4BA8r/PZsa v+Hc4EGgHq2aWf6lmuInD7T00StWHU7N+b10PDqwt1V6wPs/T4klI9XEqRe80S+DJrz/7p MszUBxcAfJjTUwwjXIYOwNlb13YDhpFtzjSjKA2qGwDP8X6M5Q2869MaTTlGUWpIMomPEo tQWskGMV6+LZm+yKZMEcc76g591Tb0jJA8JJ3j8T4EtvnrwYWNmHVLPQ8z/gIQ== From: "Ying Huang" Cc: "Ying Huang" Message-Id: <20230411081141.1762395-4-ying.huang@oss.cipunited.com> X-Lms-Return-Path: In-Reply-To: <20230411081141.1762395-1-ying.huang@oss.cipunited.com> Subject: [PATCH 3/5] elflint: Fix invalid type of relocation info and other issues on mips References: <20230411081141.1762395-1-ying.huang@oss.cipunited.com> To: Mime-Version: 1.0 X-Original-From: "Ying Huang" X-Mailer: git-send-email 2.30.2 Date: Tue, 11 Apr 2023 16:12:46 +0800 X-Spam-Status: No, score=-9.9 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, GIT_PATCH_0, HTML_MESSAGE, 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 add some check related functions --- backends/mips_init.c | 3 +++ backends/mips_symbol.c | 33 +++++++++++++++++++++++++++++++++ libebl/eblrelocvaliduse.c | 8 ++++++-- src/elflint.c | 23 ++++++++++++++++++++--- 4 files changed, 62 insertions(+), 5 deletions(-) diff --git a/backends/mips_init.c b/backends/mips_init.c index 5bba822b..4c2f21b9 100644 --- a/backends/mips_init.c +++ b/backends/mips_init.c @@ -51,6 +51,9 @@ mips_init (Elf *elf __attribute__ ((unused)), HOOK (eh, segment_type_name); HOOK (eh, dynamic_tag_check); HOOK (eh, dynamic_tag_name); + HOOK (eh, machine_section_flag_check); HOOK (eh, check_object_attribute); + HOOK (eh, check_special_symbol); + HOOK (eh, check_reloc_target_type); return eh; } diff --git a/backends/mips_symbol.c b/backends/mips_symbol.c index e760d58d..8787fcee 100644 --- a/backends/mips_symbol.c +++ b/backends/mips_symbol.c @@ -158,6 +158,39 @@ mips_section_type_name (int type, return NULL; } +bool +mips_check_reloc_target_type (Ebl *ebl __attribute__ ((unused)), Elf64_Word sh_type) +{ + return (sh_type == SHT_MIPS_DWARF); +} + +/* Check whether given symbol's st_value and st_size are OK despite failing + normal checks. */ +bool +mips_check_special_symbol (Elf *elf, + const GElf_Sym *sym __attribute__ ((unused)), + const char *name __attribute__ ((unused)), + const GElf_Shdr *destshdr) +{ + size_t shstrndx; + if (elf_getshdrstrndx (elf, &shstrndx) != 0) + return false; + const char *sname = elf_strptr (elf, shstrndx, destshdr->sh_name); + if (sname == NULL) + return false; + return (strcmp (sname, ".got") == 0 || strcmp (sname, ".bss") == 0); +} + +/* Check whether SHF_MASKPROC flags are valid. */ +bool +mips_machine_section_flag_check (GElf_Xword sh_flags) +{ + return ((sh_flags &~ (SHF_MIPS_GPREL | + SHF_MIPS_MERGE | + SHF_MIPS_ADDR | + SHF_MIPS_STRINGS)) == 0); +} + /* Check whether machine flags are valid. */ bool mips_machine_flag_check (GElf_Word flags) diff --git a/libebl/eblrelocvaliduse.c b/libebl/eblrelocvaliduse.c index f0bed345..44b8d300 100644 --- a/libebl/eblrelocvaliduse.c +++ b/libebl/eblrelocvaliduse.c @@ -32,10 +32,14 @@ #endif #include - +#include bool ebl_reloc_valid_use (Ebl *ebl, int reloc) { - return ebl != NULL ? ebl->reloc_valid_use (ebl->elf, reloc) : false; + int relocNew = reloc; + GElf_Ehdr ehdr; + if(ebl->elf->class == ELFCLASS64 && gelf_getehdr(ebl->elf, &ehdr) != NULL && ehdr.e_machine == EM_MIPS) + relocNew = ELF64_MIPS_R_TYPE(reloc); + return ebl != NULL ? ebl->reloc_valid_use (ebl->elf, relocNew) : false; } diff --git a/src/elflint.c b/src/elflint.c index dd42dcb4..04f1ee92 100644 --- a/src/elflint.c +++ b/src/elflint.c @@ -935,7 +935,10 @@ section [%2d] '%s': symbol %zu (%s): non-local symbol outside range described in } if (GELF_ST_TYPE (sym->st_info) == STT_SECTION - && GELF_ST_BIND (sym->st_info) != STB_LOCAL) + && GELF_ST_BIND (sym->st_info) != STB_LOCAL + && ehdr->e_machine != EM_MIPS + && strcmp (name, "_DYNAMIC_LINK") != 0 + && strcmp (name, "_DYNAMIC_LINKING") != 0) ERROR (_("\ section [%2d] '%s': symbol %zu (%s): non-local section symbol\n"), idx, section_name (ebl, idx), cnt, name); @@ -3789,6 +3792,12 @@ cannot get section header for section [%2zu] '%s': %s\n"), && ebl_bss_plt_p (ebl)) good_type = SHT_NOBITS; + if (ehdr->e_machine == EM_MIPS + && (strstr(special_sections[s].name, ".debug") != NULL)) + { + good_type = SHT_MIPS_DWARF; + } + /* In a debuginfo file, any normal section can be SHT_NOBITS. This is only invalid for DWARF sections and .shstrtab. */ if (shdr->sh_type != good_type @@ -3953,8 +3962,16 @@ section [%2zu] '%s': size not multiple of entry size\n"), sh_flags &= ~(GElf_Xword) SHF_MASKPROC; } if (sh_flags & SHF_MASKOS) - if (gnuld) - sh_flags &= ~(GElf_Xword) SHF_GNU_RETAIN; + { + if (gnuld) + sh_flags &= ~(GElf_Xword) SHF_GNU_RETAIN; + if (ehdr->e_machine == EM_MIPS) + { + if(sh_flags == SHF_MIPS_NOSTRIP || sh_flags == SHF_MIPS_LOCAL + || sh_flags == SHF_MIPS_NAMES || sh_flags == SHF_MIPS_NODUPE) + sh_flags &= ~shdr->sh_flags; + } + } if (sh_flags != 0) ERROR (_("section [%2zu] '%s' contains unknown flag(s)" " %#" PRIx64 "\n"), From patchwork Tue Apr 11 08:12:48 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ying Huang X-Patchwork-Id: 67619 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 8E0F13857009 for ; Tue, 11 Apr 2023 08:13:37 +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.32]) by sourceware.org (Postfix) with UTF8SMTPS id BD819385773D for ; Tue, 11 Apr 2023 08:13:06 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org BD819385773D 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=1681200779; h=from:subject:mime-version:from:date:message-id:subject:to:cc: reply-to:content-type:mime-version:in-reply-to:message-id; bh=lXbRDCrSNt4VlRFEdWAhVM/CpMkaQBGB031mA8MiWu8=; b=plnpe6VbGCEDR71JRPVLTv2mWbJIo1UlQi4ypMpe4IpMCB6p247tuu83QwixC3La2FtQ7z a/nYgDo2TV/6MGIBMkLnlfVJ0RuI+01U2AYls2+P5WqQLoiwhhQt/8A5UpbYKzXD0BI/SZ g1oULd5Fo75TtnSBq89xPeMNeuR0DbzOH7Qb3Fy7wuR95jT9N9ZBXrE8GvWPRg7H2TgY/m 1CkiKBaPZlqQ6jkC+YvTKVgFmg2+cU7DaODXeE0+6zL8qrt8dIYMU0cfLU0+M1z2rzSCCn f8S4UwcJ1/DKNHPUEexSYmSeV5I09p2BnpnbrtH+eGUrQ/gu8NKy4Ac+0zS/Cg== Cc: "Ying Huang" Date: Tue, 11 Apr 2023 16:12:48 +0800 Message-Id: <20230411081141.1762395-5-ying.huang@oss.cipunited.com> References: <20230411081141.1762395-1-ying.huang@oss.cipunited.com> X-Lms-Return-Path: To: X-Original-From: "Ying Huang" X-Mailer: git-send-email 2.30.2 From: "Ying Huang" Mime-Version: 1.0 Subject: [PATCH 4/5] stack: Fix stack unwind failure on mips In-Reply-To: <20230411081141.1762395-1-ying.huang@oss.cipunited.com> X-Spam-Status: No, score=-11.7 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 add abi_cfi, set_initial_registers_tid, unwind on mips. "./src/stack -p PID" can show stack information --- backends/Makefile.am | 3 +- backends/mips_cfi.c | 68 +++++++++++++++++++++++++++++++++ backends/mips_init.c | 4 ++ backends/mips_initreg.c | 70 ++++++++++++++++++++++++++++++++++ backends/mips_unwind.c | 84 +++++++++++++++++++++++++++++++++++++++++ 5 files changed, 228 insertions(+), 1 deletion(-) create mode 100644 backends/mips_cfi.c create mode 100644 backends/mips_initreg.c create mode 100644 backends/mips_unwind.c diff --git a/backends/Makefile.am b/backends/Makefile.am index 428a1a03..ddc31c9d 100644 --- a/backends/Makefile.am +++ b/backends/Makefile.am @@ -100,7 +100,8 @@ loongarch_SRCS = loongarch_init.c loongarch_symbol.c arc_SRCS = arc_init.c arc_symbol.c -mips_SRCS = mips_init.c mips_symbol.c mips_attrs.c +mips_SRCS = mips_init.c mips_symbol.c mips_attrs.c mips_initreg.c \ + mips_cfi.c mips_unwind.c libebl_backends_a_SOURCES = $(i386_SRCS) $(sh_SRCS) $(x86_64_SRCS) \ $(ia64_SRCS) $(alpha_SRCS) $(arm_SRCS) \ diff --git a/backends/mips_cfi.c b/backends/mips_cfi.c new file mode 100644 index 00000000..77132cc1 --- /dev/null +++ b/backends/mips_cfi.c @@ -0,0 +1,68 @@ +/* MIPS ABI-specified defaults for DWARF CFI. + Copyright (C) 2009 Red Hat, Inc. + Copyright (C) 2023 CIP United Inc. + This file is part of elfutils. + + This file is free software; you can redistribute it and/or modify + it under the terms of either + + * the GNU Lesser General Public License as published by the Free + Software Foundation; either version 3 of the License, or (at + your option) any later version + + or + + * the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at + your option) any later version + + or both in parallel, as here. + + elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received copies of the GNU General Public License and + the GNU Lesser General Public License along with this program. If + not, see . */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +#define BACKEND mips_ +#include "libebl_CPU.h" + +int +mips_abi_cfi (Ebl *ebl __attribute__ ((unused)), Dwarf_CIE *abi_info) +{ + static const uint8_t abi_cfi[] = + { + DW_CFA_def_cfa, ULEB128_7 (31), ULEB128_7 (0), + /* Callee-saved regs. */ + DW_CFA_same_value, ULEB128_7 (16), /* s0 */ + DW_CFA_same_value, ULEB128_7 (17), /* s1 */ + DW_CFA_same_value, ULEB128_7 (18), /* s2 */ + DW_CFA_same_value, ULEB128_7 (19), /* s3 */ + DW_CFA_same_value, ULEB128_7 (20), /* s4 */ + DW_CFA_same_value, ULEB128_7 (21), /* s5 */ + DW_CFA_same_value, ULEB128_7 (22), /* s6 */ + DW_CFA_same_value, ULEB128_7 (23), /* s7 */ + DW_CFA_same_value, ULEB128_7 (28), /* gp */ + DW_CFA_same_value, ULEB128_7 (29), /* sp */ + DW_CFA_same_value, ULEB128_7 (30), /* fp */ + + DW_CFA_val_offset, ULEB128_7 (29), ULEB128_7 (0), + }; + + abi_info->initial_instructions = abi_cfi; + abi_info->initial_instructions_end = &abi_cfi[sizeof abi_cfi]; + abi_info->data_alignment_factor = -4; + + abi_info->return_address_register = 31; /* %ra */ + + return 0; +} diff --git a/backends/mips_init.c b/backends/mips_init.c index 4c2f21b9..3caa9fee 100644 --- a/backends/mips_init.c +++ b/backends/mips_init.c @@ -55,5 +55,9 @@ mips_init (Elf *elf __attribute__ ((unused)), HOOK (eh, check_object_attribute); HOOK (eh, check_special_symbol); HOOK (eh, check_reloc_target_type); + HOOK (eh, set_initial_registers_tid); + HOOK (eh, abi_cfi); + HOOK (eh, unwind); + eh->frame_nregs = 32; return eh; } diff --git a/backends/mips_initreg.c b/backends/mips_initreg.c new file mode 100644 index 00000000..31b8de13 --- /dev/null +++ b/backends/mips_initreg.c @@ -0,0 +1,70 @@ +/* Fetch live process registers from TID. + Copyright (C) 2023 CIP United Inc. + This file is part of elfutils. + + This file is free software; you can redistribute it and/or modify + it under the terms of either + + * the GNU Lesser General Public License as published by the Free + Software Foundation; either version 3 of the License, or (at + your option) any later version + + or + + * the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at + your option) any later version + + or both in parallel, as here. + + elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received copies of the GNU General Public License and + the GNU Lesser General Public License along with this program. If + not, see . */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#if (defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__)) && defined(__linux__) +# include +# include +#endif + +#define BACKEND mips_ +#include "libebl_CPU.h" +#include + + +bool +mips_set_initial_registers_tid (pid_t tid __attribute__ ((unused)), + ebl_tid_registers_t *setfunc __attribute__ ((unused)), + void *arg __attribute__ ((unused))) +{ +#if (!defined(mips) && !defined(__mips) && !defined(__mips__) && !defined(MIPS) && !defined(__MIPS__)) || !defined(__linux__) + return false; +#else /* __mips__ */ +/* For PTRACE_GETREGS */ +struct pt_regs { + uint64_t regs[32]; + uint64_t lo; + uint64_t hi; + uint64_t pc; + uint64_t badvaddr; + uint64_t cause; + uint64_t status; +}; + + struct pt_regs gregs; + if (ptrace (PTRACE_GETREGS, tid, 0, &gregs) != 0) + return false; + if (! setfunc (-1, 1, (Dwarf_Word *) &gregs.pc, arg)) + return false; + return setfunc (0, 32, (Dwarf_Word *) &gregs.regs[0], arg); +#endif /* __mips__ */ +} diff --git a/backends/mips_unwind.c b/backends/mips_unwind.c new file mode 100644 index 00000000..d09db3a9 --- /dev/null +++ b/backends/mips_unwind.c @@ -0,0 +1,84 @@ +/* Get previous frame state for an existing frame state. + Copyright (C) 2016 The Qt Company Ltd. + Copyright (C) 2023 CIP United Inc. + This file is part of elfutils. + + This file is free software; you can redistribute it and/or modify + it under the terms of either + + * the GNU Lesser General Public License as published by the Free + Software Foundation; either version 3 of the License, or (at + your option) any later version + + or + + * the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at + your option) any later version + + or both in parallel, as here. + + elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received copies of the GNU General Public License and + the GNU Lesser General Public License along with this program. If + not, see . */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#define BACKEND mips_ +#define SP_REG 29 +#define FP_REG 30 +#define LR_REG 31 +#define FP_OFFSET 0 +#define LR_OFFSET 8 +#define SP_OFFSET 16 + +#include "libebl_CPU.h" + +/* There was no CFI. Maybe we happen to have a frame pointer and can unwind from that? */ + +bool +EBLHOOK(unwind) (Ebl *ebl __attribute__ ((unused)), Dwarf_Addr pc __attribute__ ((unused)), + ebl_tid_registers_t *setfunc, ebl_tid_registers_get_t *getfunc, + ebl_pid_memory_read_t *readfunc, void *arg, + bool *signal_framep __attribute__ ((unused))) +{ + Dwarf_Word fp, lr, sp; + + if (!getfunc(LR_REG, 1, &lr, arg)) + return false; + + if (lr == 0 || !setfunc(-1, 1, &lr, arg)) + return false; + + if (!getfunc(FP_REG, 1, &fp, arg)) + fp = 0; + + if (!getfunc(SP_REG, 1, &sp, arg)) + sp = 0; + + Dwarf_Word newLr, newFp, newSp; + + if (!readfunc(fp + LR_OFFSET, &newLr, arg)) + newLr = 0; + + if (!readfunc(fp + FP_OFFSET, &newFp, arg)) + newFp = 0; + + newSp = fp + SP_OFFSET; + + // These are not fatal if they don't work. They will just prevent unwinding at the next frame. + setfunc(LR_REG, 1, &newLr, arg); + setfunc(FP_REG, 1, &newFp, arg); + setfunc(SP_REG, 1, &newSp, arg); + + // If the fp is invalid, we might still have a valid lr. + // But if the fp is valid, then the stack should be moving in the right direction. + return fp == 0 || newSp > sp; +} From patchwork Tue Apr 11 08:12:50 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ying Huang X-Patchwork-Id: 67617 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 714EF3857712 for ; Tue, 11 Apr 2023 08:13:15 +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.38]) by sourceware.org (Postfix) with UTF8SMTPS id 410AA385842C for ; Tue, 11 Apr 2023 08:13:07 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 410AA385842C 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=1681200782; h=from:subject:mime-version:from:date:message-id:subject:to:cc: reply-to:content-type:mime-version:in-reply-to:message-id; bh=oyxTyKcgX76TiBUP+iCO3KuFHIGMu2JABwF6OAdTQvE=; b=I1Xw6YXs2JopvX66FEG8VCe9h2zLrVCEwCnzLeUdRplDYIBpSXPtVI8MGLcZXd/+hShV3g R9SVL74H4vXcCrrceoTYbHHQDlxDYKlOu6yE0jlcIAG905FHNU60jkyjHkYtIqD9ONV4Y6 zGR5ovxKKdDG3JobL/HEvavCZRS8N68QfvEOqlud4fbpELY6V3IW6VRHBFEl7+IAGbz/P/ w+PQ1qxZr937+k3cxb7zXkl+4WrP5PYxfpqyZ1AuM7ZkIfHpLMCNqhX75I+G86EPp7L3GH PtbEcO/AQOqFZIq42fKQzrEqVuNqOBrvc0aG1DCPqUlQHBzgRiOolaE3lLbMYg== X-Lms-Return-Path: To: Date: Tue, 11 Apr 2023 16:12:50 +0800 X-Mailer: git-send-email 2.30.2 X-Original-From: "Ying Huang" Subject: [PATCH 5/5] backends: Fix run-native-test.sh and run-funcretval++11.sh run fail on mips Message-Id: <20230411081141.1762395-6-ying.huang@oss.cipunited.com> From: "Ying Huang" References: <20230411081141.1762395-1-ying.huang@oss.cipunited.com> In-Reply-To: <20230411081141.1762395-1-ying.huang@oss.cipunited.com> Cc: "Ying Huang" Mime-Version: 1.0 X-Spam-Status: No, score=-12.1 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 add register_info, return_value_location function on mips --- backends/Makefile.am | 2 +- backends/mips_init.c | 2 + backends/mips_regs.c | 109 +++++++++++++++++ backends/mips_retval.c | 261 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 373 insertions(+), 1 deletion(-) create mode 100644 backends/mips_regs.c create mode 100644 backends/mips_retval.c diff --git a/backends/Makefile.am b/backends/Makefile.am index ddc31c9d..5453f787 100644 --- a/backends/Makefile.am +++ b/backends/Makefile.am @@ -101,7 +101,7 @@ loongarch_SRCS = loongarch_init.c loongarch_symbol.c arc_SRCS = arc_init.c arc_symbol.c mips_SRCS = mips_init.c mips_symbol.c mips_attrs.c mips_initreg.c \ - mips_cfi.c mips_unwind.c + mips_cfi.c mips_unwind.c mips_regs.c mips_retval.c libebl_backends_a_SOURCES = $(i386_SRCS) $(sh_SRCS) $(x86_64_SRCS) \ $(ia64_SRCS) $(alpha_SRCS) $(arm_SRCS) \ diff --git a/backends/mips_init.c b/backends/mips_init.c index 3caa9fee..7ca93314 100644 --- a/backends/mips_init.c +++ b/backends/mips_init.c @@ -58,6 +58,8 @@ mips_init (Elf *elf __attribute__ ((unused)), HOOK (eh, set_initial_registers_tid); HOOK (eh, abi_cfi); HOOK (eh, unwind); + HOOK (eh, register_info); + HOOK (eh, return_value_location); eh->frame_nregs = 32; return eh; } diff --git a/backends/mips_regs.c b/backends/mips_regs.c new file mode 100644 index 00000000..733caeee --- /dev/null +++ b/backends/mips_regs.c @@ -0,0 +1,109 @@ +/* Register names and numbers for mips DWARF. + Copyright (C) 2006 Red Hat, Inc. + Copyright (C) 2023 CIP United Inc. + This file is part of elfutils. + + This file is free software; you can redistribute it and/or modify + it under the terms of either + + * the GNU Lesser General Public License as published by the Free + Software Foundation; either version 3 of the License, or (at + your option) any later version + + or + + * the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at + your option) any later version + + or both in parallel, as here. + + elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received copies of the GNU General Public License and + the GNU Lesser General Public License along with this program. If + not, see . */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include + +#define BACKEND mips_ +#include "libebl_CPU.h" + +ssize_t +mips_register_info (Ebl *ebl __attribute__ ((unused)), + int regno, char *name, size_t namelen, + const char **prefix, const char **setname, + int *bits, int *type) +{ + if (name == NULL) + return 66; + + if (regno < 0 || regno > 65 || namelen < 4) + return -1; + + *prefix = "$"; + + if (regno < 32) + { + *setname = "integer"; + *type = DW_ATE_signed; + *bits = 32; + if (regno < 32 + 10) + { + name[0] = regno + '0'; + namelen = 1; + } + else + { + name[0] = (regno / 10) + '0'; + name[1] = (regno % 10) + '0'; + namelen = 2; + } + } + else if (regno < 64) + { + *setname = "FPU"; + *type = DW_ATE_float; + *bits = 32; + name[0] = 'f'; + if (regno < 32 + 10) + { + name[1] = (regno - 32) + '0'; + namelen = 2; + } + else + { + name[1] = (regno - 32) / 10 + '0'; + name[2] = (regno - 32) % 10 + '0'; + namelen = 3; + } + } + else if (regno == 64) + { + *type = DW_ATE_signed; + *bits = 32; + name[0] = 'h'; + name[1] = 'i'; + namelen = 2; + } + else + { + *type = DW_ATE_signed; + *bits = 32; + name[0] = 'l'; + name[1] = 'o'; + namelen = 2; + } + + name[namelen++] = '\0'; + return namelen; +} diff --git a/backends/mips_retval.c b/backends/mips_retval.c new file mode 100644 index 00000000..fd9aaefa --- /dev/null +++ b/backends/mips_retval.c @@ -0,0 +1,261 @@ +/* Function return value location for Linux/mips ABI. + Copyright (C) 2005 Red Hat, Inc. + Copyright (C) 2023 CIP United Inc. + This file is part of elfutils. + + This file is free software; you can redistribute it and/or modify + it under the terms of either + + * the GNU Lesser General Public License as published by the Free + Software Foundation; either version 3 of the License, or (at + your option) any later version + + or + + * the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at + your option) any later version + + or both in parallel, as here. + + elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received copies of the GNU General Public License and + the GNU Lesser General Public License along with this program. If + not, see . */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include +#include +#include + +#define BACKEND mips_ +#include "libebl_CPU.h" +#include "libdwP.h" + +/* All the possible MIPS ARCHs. */ +enum mips_arch + { + MIPS_ARCH_UNKNOWN = 0, + MIPS_ARCH_32, + MIPS_ARCH_64, + MIPS_ARCH_LAST + }; + +/* Find the mips ARCH of the current file */ +enum mips_arch find_mips_arch(Elf *elf) +{ + GElf_Ehdr ehdr_mem; + GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem); + + if (ehdr == NULL) + return MIPS_ARCH_LAST; + + GElf_Word elf_flags = ehdr->e_flags; + + /* Check elf_flags to see if it specifies the ARCH being used. */ + switch ((elf_flags & EF_MIPS_ARCH)) + { + case E_MIPS_ARCH_32: + case EF_MIPS_ARCH_32R2: + case E_MIPS_ARCH_32R6: + return MIPS_ARCH_32; + case E_MIPS_ARCH_64: + case EF_MIPS_ARCH_64R2: + case E_MIPS_ARCH_64R6: + return MIPS_ARCH_64; + default: + return MIPS_ARCH_32; + } + + return MIPS_ARCH_UNKNOWN; +} + +unsigned int +mips_arch_regsize (enum mips_arch arch) +{ + switch (arch) + { + case MIPS_ARCH_32: + return 4; + case MIPS_ARCH_64: + return 8; + case MIPS_ARCH_UNKNOWN: + case MIPS_ARCH_LAST: + default: + return 0; + } +} + +/* $v0 or pair $v0, $v1 */ +static const Dwarf_Op loc_intreg_o32[] = + { + { .atom = DW_OP_reg2 }, { .atom = DW_OP_piece, .number = 4 }, + { .atom = DW_OP_reg3 }, { .atom = DW_OP_piece, .number = 4 }, + }; + +static const Dwarf_Op loc_intreg[] = + { + { .atom = DW_OP_reg2 }, { .atom = DW_OP_piece, .number = 8 }, + { .atom = DW_OP_reg3 }, { .atom = DW_OP_piece, .number = 8 }, + }; +#define nloc_intreg 1 +#define nloc_intregpair 4 + +/* $f0 (float), or pair $f0, $f1 (double). + * f2/f3 are used for COMPLEX (= 2 doubles) returns in Fortran */ +static const Dwarf_Op loc_fpreg_o32[] = + { + { .atom = DW_OP_regx, .number = 32 }, { .atom = DW_OP_piece, .number = 4 }, + { .atom = DW_OP_regx, .number = 33 }, { .atom = DW_OP_piece, .number = 4 }, + { .atom = DW_OP_regx, .number = 34 }, { .atom = DW_OP_piece, .number = 4 }, + { .atom = DW_OP_regx, .number = 35 }, { .atom = DW_OP_piece, .number = 4 }, + }; + +/* $f0, or pair $f0, $f2. */ +static const Dwarf_Op loc_fpreg[] = + { + { .atom = DW_OP_regx, .number = 32 }, { .atom = DW_OP_piece, .number = 8 }, + { .atom = DW_OP_regx, .number = 34 }, { .atom = DW_OP_piece, .number = 8 }, + }; +#define nloc_fpreg 1 +#define nloc_fpregpair 4 +#define nloc_fpregquad 8 + +/* The return value is a structure and is actually stored in stack space + passed in a hidden argument by the caller. But, the compiler + helpfully returns the address of that space in $v0. */ +static const Dwarf_Op loc_aggregate[] = + { + { .atom = DW_OP_breg2, .number = 0 } + }; +#define nloc_aggregate 1 + +int +mips_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp) +{ + /* First find the ARCH used by the elf object */ + enum mips_arch arch = find_mips_arch(functypedie->cu->dbg->elf); + /* Something went seriously wrong while trying to figure out the ARCH */ + if (arch == MIPS_ARCH_LAST) + return -1; + + /* We couldn't identify the ARCH, but the file seems valid */ + if (arch == MIPS_ARCH_UNKNOWN) + return -3; + + unsigned int regsize = mips_arch_regsize (arch); + if (!regsize) + return -2; + + /* Start with the function's type, and get the DW_AT_type attribute, + which is the type of the return value. */ + + Dwarf_Attribute attr_mem; + Dwarf_Attribute *attr = dwarf_attr_integrate (functypedie, DW_AT_type, &attr_mem); + if (attr == NULL) + /* The function has no return value, like a `void' function in C. */ + return 0; + + Dwarf_Die die_mem; + Dwarf_Die *typedie = dwarf_formref_die (attr, &die_mem); + int tag = dwarf_tag (typedie); + + /* Follow typedefs and qualifiers to get to the actual type. */ + while (tag == DW_TAG_typedef + || tag == DW_TAG_const_type || tag == DW_TAG_volatile_type + || tag == DW_TAG_restrict_type) + { + attr = dwarf_attr_integrate (typedie, DW_AT_type, &attr_mem); + typedie = dwarf_formref_die (attr, &die_mem); + tag = dwarf_tag (typedie); + } + + switch (tag) + { + case -1: + return -1; + + case DW_TAG_subrange_type: + if (! dwarf_hasattr_integrate (typedie, DW_AT_byte_size)) + { + attr = dwarf_attr_integrate (typedie, DW_AT_type, &attr_mem); + typedie = dwarf_formref_die (attr, &die_mem); + tag = dwarf_tag (typedie); + } + /* Fall through. */ + FALLTHROUGH; + + case DW_TAG_base_type: + case DW_TAG_enumeration_type: + CASE_POINTER: + { + Dwarf_Word size; + if (dwarf_formudata (dwarf_attr_integrate (typedie, DW_AT_byte_size, + &attr_mem), &size) != 0) + { + if (dwarf_is_pointer (tag)) + size = regsize; + else + return -1; + } + if (tag == DW_TAG_base_type) + { + Dwarf_Word encoding; + if (dwarf_formudata (dwarf_attr_integrate (typedie, DW_AT_encoding, + &attr_mem), &encoding) != 0) + return -1; + +#define ARCH_LOC(loc, regsize) ((regsize) == 4 ? (loc ## _o32) : (loc)) + + if (encoding == DW_ATE_float) + { + *locp = ARCH_LOC(loc_fpreg, regsize); + if (size <= regsize) + return nloc_fpreg; + + if (size <= 2*regsize) + return nloc_fpregpair; + + if (size <= 4*regsize && arch == MIPS_ARCH_32) + return nloc_fpregquad; + + goto aggregate; + } + } + *locp = ARCH_LOC(loc_intreg, regsize); + if (size <= regsize) + return nloc_intreg; + if (size <= 2*regsize) + return nloc_intregpair; + + /* Else fall through. Shouldn't happen though (at least with gcc) */ + } + FALLTHROUGH; + + case DW_TAG_structure_type: + case DW_TAG_class_type: + case DW_TAG_union_type: + case DW_TAG_array_type: + aggregate: + /* XXX TODO: Can't handle structure return with other ABI's yet :-/ */ + if ((arch != MIPS_ARCH_32) && (arch != MIPS_ARCH_64)) + return -2; + + *locp = loc_aggregate; + return nloc_aggregate; + } + + /* XXX We don't have a good way to return specific errors from ebl calls. + This value means we do not understand the type, but it is well-formed + DWARF and might be valid. */ + return -2; +}