blob: 8a65e4e4640ad359d28d1e87c0cf0a62331ea76d [file] [log] [blame]
b.liue9582032025-04-17 19:18:16 +08001From 8d3bb7db9d6f07decfc59d83988cda54e5a8b0cd Mon Sep 17 00:00:00 2001
2From: Ying Huang <ying.huang@oss.cipunited.com>
3Date: Tue, 5 Mar 2024 17:51:17 +0800
4Subject: [PATCH 1/7] Support Mips architecture
5
6 * backends/Makefile.am (modules): Add mips.
7 (mips_SRCS): New var for mips_init.c mips_symbol.c.
8 (libebl_backends_a_SOURCES): Add mips_SRCS.
9 * backends/mips_init.c: New file.
10 * backends/mips_reloc.def: Likewise.
11 * backends/mips_symbol.c: Likewise.
12 * libebl/eblopenbackend.c (mips_init): Declare.
13 (machines): Add mips.
14 * libelf/libelfP.h: Add ELF64_MIPS_R_TYPE{1,2,3}
15
16Signed-off-by: Ying Huang <ying.huang@oss.cipunited.com>
17---
18 backends/Makefile.am | 6 ++-
19 backends/mips_init.c | 52 +++++++++++++++++++++++
20 backends/mips_reloc.def | 93 +++++++++++++++++++++++++++++++++++++++++
21 backends/mips_symbol.c | 63 ++++++++++++++++++++++++++++
22 libebl/eblopenbackend.c | 2 +
23 libelf/libelfP.h | 3 ++
24 6 files changed, 217 insertions(+), 2 deletions(-)
25 create mode 100644 backends/mips_init.c
26 create mode 100644 backends/mips_reloc.def
27 create mode 100644 backends/mips_symbol.c
28
29--- a/backends/Makefile.am
30+++ b/backends/Makefile.am
31@@ -37,7 +37,7 @@ AM_CPPFLAGS += -I$(top_srcdir)/libebl -I
32 noinst_LIBRARIES = libebl_backends.a libebl_backends_pic.a
33
34 modules = i386 sh x86_64 ia64 alpha arm aarch64 sparc ppc ppc64 s390 \
35- m68k bpf riscv csky loongarch arc
36+ m68k bpf riscv csky loongarch arc mips
37
38 i386_SRCS = i386_init.c i386_symbol.c i386_corenote.c i386_cfi.c \
39 i386_retval.c i386_regs.c i386_auxv.c \
40@@ -102,12 +102,16 @@ loongarch_SRCS = loongarch_init.c loonga
41
42 arc_SRCS = arc_init.c arc_symbol.c
43
44+mips_SRCS = mips_init.c mips_symbol.c mips_attrs.c mips_initreg.c \
45+ mips_cfi.c mips_unwind.c mips_regs.c mips_retval.c \
46+ mips_corenote.c mips64_corenote.c
47+
48 libebl_backends_a_SOURCES = $(i386_SRCS) $(sh_SRCS) $(x86_64_SRCS) \
49 $(ia64_SRCS) $(alpha_SRCS) $(arm_SRCS) \
50 $(aarch64_SRCS) $(sparc_SRCS) $(ppc_SRCS) \
51 $(ppc64_SRCS) $(s390_SRCS) \
52 $(m68k_SRCS) $(bpf_SRCS) $(riscv_SRCS) $(csky_SRCS) \
53- $(loongarch_SRCS) $(arc_SRCS)
54+ $(loongarch_SRCS) $(arc_SRCS) $(mips_SRCS)
55
56 libebl_backends_pic_a_SOURCES =
57 am_libebl_backends_pic_a_OBJECTS = $(libebl_backends_a_SOURCES:.c=.os)
58--- /dev/null
59+++ b/backends/mips_init.c
60@@ -0,0 +1,74 @@
61+/* Initialization of MIPS specific backend library.
62+ Copyright (C) 2024 CIP United Inc.
63+ This file is part of elfutils.
64+
65+ This file is free software; you can redistribute it and/or modify
66+ it under the terms of either
67+
68+ * the GNU Lesser General Public License as published by the Free
69+ Software Foundation; either version 3 of the License, or (at
70+ your option) any later version
71+
72+ or
73+
74+ * the GNU General Public License as published by the Free
75+ Software Foundation; either version 2 of the License, or (at
76+ your option) any later version
77+
78+ or both in parallel, as here.
79+
80+ elfutils is distributed in the hope that it will be useful, but
81+ WITHOUT ANY WARRANTY; without even the implied warranty of
82+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
83+ General Public License for more details.
84+
85+ You should have received copies of the GNU General Public License and
86+ the GNU Lesser General Public License along with this program. If
87+ not, see <http://www.gnu.org/licenses/>. */
88+
89+#ifdef HAVE_CONFIG_H
90+# include <config.h>
91+#endif
92+
93+#define BACKEND mips_
94+#define RELOC_PREFIX R_MIPS_
95+#include "libebl_CPU.h"
96+#include "libelfP.h"
97+
98+#define RELOC_TYPE_ID(type) ((type) & 0xff)
99+
100+/* This defines the common reloc hooks based on mips_reloc.def. */
101+#include "common-reloc.c"
102+
103+extern __typeof (EBLHOOK (core_note)) mips64_core_note attribute_hidden;
104+
105+Ebl *
106+mips_init (Elf *elf __attribute__ ((unused)),
107+ GElf_Half machine __attribute__ ((unused)),
108+ Ebl *eh)
109+{
110+ /* We handle it. */
111+ mips_init_reloc (eh);
112+ HOOK (eh, reloc_simple_type);
113+ HOOK (eh, section_type_name);
114+ HOOK (eh, machine_flag_check);
115+ HOOK (eh, machine_flag_name);
116+ HOOK (eh, machine_section_flag_check);
117+ HOOK (eh, segment_type_name);
118+ HOOK (eh, dynamic_tag_check);
119+ HOOK (eh, dynamic_tag_name);
120+ HOOK (eh, check_object_attribute);
121+ HOOK (eh, check_special_symbol);
122+ HOOK (eh, check_reloc_target_type);
123+ HOOK (eh, set_initial_registers_tid);
124+ HOOK (eh, abi_cfi);
125+ HOOK (eh, unwind);
126+ HOOK (eh, register_info);
127+ HOOK (eh, return_value_location);
128+ if (eh->class == ELFCLASS64)
129+ eh->core_note = mips64_core_note;
130+ else
131+ HOOK (eh, core_note);
132+ eh->frame_nregs = 71;
133+ return eh;
134+}
135--- /dev/null
136+++ b/backends/mips_reloc.def
137@@ -0,0 +1,93 @@
138+/* List the relocation types for MIPS. -*- C -*-
139+ Copyright (C) 2024 CIP United Inc.
140+ This file is part of elfutils.
141+
142+ This file is free software; you can redistribute it and/or modify
143+ it under the terms of either
144+
145+ * the GNU Lesser General Public License as published by the Free
146+ Software Foundation; either version 3 of the License, or (at
147+ your option) any later version
148+
149+ or
150+
151+ * the GNU General Public License as published by the Free
152+ Software Foundation; either version 2 of the License, or (at
153+ your option) any later version
154+
155+ or both in parallel, as here.
156+
157+ elfutils is distributed in the hope that it will be useful, but
158+ WITHOUT ANY WARRANTY; without even the implied warranty of
159+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
160+ General Public License for more details.
161+
162+ You should have received copies of the GNU General Public License and
163+ the GNU Lesser General Public License along with this program. If
164+ not, see <http://www.gnu.org/licenses/>. */
165+
166+/* NAME, REL|EXEC|DYN */
167+
168+
169+RELOC_TYPE (NONE, REL|EXEC|DYN)
170+RELOC_TYPE (16, REL|EXEC|DYN)
171+RELOC_TYPE (32, REL)
172+RELOC_TYPE (REL32, REL|EXEC|DYN)
173+RELOC_TYPE (26, REL|DYN)
174+RELOC_TYPE (HI16, REL)
175+RELOC_TYPE (LO16, REL|EXEC|DYN)
176+RELOC_TYPE (GPREL16, REL|EXEC|DYN)
177+RELOC_TYPE (LITERAL, REL|EXEC|DYN)
178+RELOC_TYPE (GOT16, REL|EXEC|DYN)
179+RELOC_TYPE (PC16, REL)
180+RELOC_TYPE (CALL16, REL)
181+RELOC_TYPE (GPREL32, REL)
182+RELOC_TYPE (SHIFT5, REL)
183+RELOC_TYPE (SHIFT6, REL)
184+RELOC_TYPE (64, REL)
185+RELOC_TYPE (GOT_DISP, REL)
186+RELOC_TYPE (GOT_PAGE, REL)
187+RELOC_TYPE (GOT_OFST, REL)
188+RELOC_TYPE (GOT_HI16, REL)
189+RELOC_TYPE (GOT_LO16, REL)
190+RELOC_TYPE (SUB, REL)
191+RELOC_TYPE (INSERT_A, REL)
192+RELOC_TYPE (INSERT_B, REL)
193+RELOC_TYPE (DELETE, REL)
194+RELOC_TYPE (HIGHER, REL)
195+RELOC_TYPE (HIGHEST, REL)
196+RELOC_TYPE (CALL_HI16, REL)
197+RELOC_TYPE (CALL_LO16, REL)
198+RELOC_TYPE (SCN_DISP, REL)
199+RELOC_TYPE (REL16, REL)
200+RELOC_TYPE (ADD_IMMEDIATE, REL)
201+RELOC_TYPE (PJUMP, REL)
202+RELOC_TYPE (RELGOT, REL)
203+RELOC_TYPE (JALR, REL)
204+RELOC_TYPE (TLS_DTPMOD32, DYN)
205+RELOC_TYPE (TLS_DTPREL32, REL)
206+RELOC_TYPE (TLS_DTPMOD64, DYN)
207+RELOC_TYPE (TLS_DTPREL64, REL)
208+RELOC_TYPE (TLS_GD, REL)
209+RELOC_TYPE (TLS_LDM, REL)
210+RELOC_TYPE (TLS_DTPREL_HI16, REL)
211+RELOC_TYPE (TLS_DTPREL_LO16, REL)
212+RELOC_TYPE (TLS_GOTTPREL, REL)
213+RELOC_TYPE (TLS_TPREL32, REL)
214+RELOC_TYPE (TLS_TPREL64, REL)
215+RELOC_TYPE (TLS_TPREL_HI16, REL)
216+RELOC_TYPE (TLS_TPREL_LO16, REL)
217+RELOC_TYPE (GLOB_DAT, REL)
218+RELOC_TYPE (PC21_S2, REL)
219+RELOC_TYPE (PC26_S2, REL)
220+RELOC_TYPE (PC18_S3, REL)
221+RELOC_TYPE (PC19_S2, REL)
222+RELOC_TYPE (PCHI16, REL)
223+RELOC_TYPE (PCLO16, REL)
224+RELOC_TYPE (COPY, REL)
225+RELOC_TYPE (JUMP_SLOT, REL)
226+RELOC_TYPE (PC32, REL)
227+RELOC_TYPE (EH, REL)
228+RELOC_TYPE (GNU_REL16_S2, REL)
229+RELOC_TYPE (GNU_VTINHERIT, REL)
230+RELOC_TYPE (GNU_VTENTRY, REL)
231--- /dev/null
232+++ b/backends/mips_symbol.c
233@@ -0,0 +1,671 @@
234+/* MIPS specific symbolic name handling.
235+ Copyright (C) 2024 CIP United Inc.
236+ This file is part of elfutils.
237+
238+ This file is free software; you can redistribute it and/or modify
239+ it under the terms of either
240+
241+ * the GNU Lesser General Public License as published by the Free
242+ Software Foundation; either version 3 of the License, or (at
243+ your option) any later version
244+
245+ or
246+
247+ * the GNU General Public License as published by the Free
248+ Software Foundation; either version 2 of the License, or (at
249+ your option) any later version
250+
251+ or both in parallel, as here.
252+
253+ elfutils is distributed in the hope that it will be useful, but
254+ WITHOUT ANY WARRANTY; without even the implied warranty of
255+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
256+ General Public License for more details.
257+
258+ You should have received copies of the GNU General Public License and
259+ the GNU Lesser General Public License along with this program. If
260+ not, see <http://www.gnu.org/licenses/>. */
261+
262+#ifdef HAVE_CONFIG_H
263+# include <config.h>
264+#endif
265+
266+#include <system.h>
267+
268+#include <elf.h>
269+#include <stddef.h>
270+#include <string.h>
271+#include <stdio.h>
272+#define BACKEND mips_
273+#include "libebl_CPU.h"
274+#include "libelfP.h"
275+
276+/* Check for the simple reloc types. */
277+Elf_Type
278+mips_reloc_simple_type (Ebl *ebl, int type,
279+ int *addsub __attribute__ ((unused)))
280+{
281+ int typeNew = type;
282+ if(ebl->elf->class == ELFCLASS64)
283+ typeNew = ELF64_MIPS_R_TYPE1(type);
284+ switch (typeNew)
285+ {
286+ case R_MIPS_64:
287+ return ELF_T_XWORD;
288+ case R_MIPS_32:
289+ return ELF_T_WORD;
290+ case R_MIPS_16:
291+ return ELF_T_HALF;
292+
293+ default:
294+ return ELF_T_NUM;
295+ }
296+}
297+
298+/* copy binutils-2.34/binutils/readelf.c get_mips_section_type_name */
299+const char *
300+mips_section_type_name (int type,
301+ char *buf __attribute__ ((unused)),
302+ size_t len __attribute__ ((unused)))
303+{
304+ switch (type)
305+ {
306+ case SHT_MIPS_LIBLIST:
307+ return "MIPS_LIBLIST";
308+ case SHT_MIPS_MSYM:
309+ return "MIPS_MSYM";
310+ case SHT_MIPS_CONFLICT:
311+ return "MIPS_CONFLICT";
312+ case SHT_MIPS_GPTAB:
313+ return "MIPS_GPTAB";
314+ case SHT_MIPS_UCODE:
315+ return "MIPS_UCODE";
316+ case SHT_MIPS_DEBUG:
317+ return "MIPS_DEBUG";
318+ case SHT_MIPS_REGINFO:
319+ return "MIPS_REGINFO";
320+ case SHT_MIPS_PACKAGE:
321+ return "MIPS_PACKAGE";
322+ case SHT_MIPS_PACKSYM:
323+ return "MIPS_PACKSYM";
324+ case SHT_MIPS_RELD:
325+ return "MIPS_RELD";
326+ case SHT_MIPS_IFACE:
327+ return "MIPS_IFACE";
328+ case SHT_MIPS_CONTENT:
329+ return "MIPS_CONTENT";
330+ case SHT_MIPS_OPTIONS:
331+ return "MIPS_OPTIONS";
332+ case SHT_MIPS_SHDR:
333+ return "MIPS_SHDR";
334+ case SHT_MIPS_FDESC:
335+ return "MIPS_FDESC";
336+ case SHT_MIPS_EXTSYM:
337+ return "MIPS_EXTSYM";
338+ case SHT_MIPS_DENSE:
339+ return "MIPS_DENSE";
340+ case SHT_MIPS_PDESC:
341+ return "MIPS_PDESC";
342+ case SHT_MIPS_LOCSYM:
343+ return "MIPS_LOCSYM";
344+ case SHT_MIPS_AUXSYM:
345+ return "MIPS_AUXSYM";
346+ case SHT_MIPS_OPTSYM:
347+ return "MIPS_OPTSYM";
348+ case SHT_MIPS_LOCSTR:
349+ return "MIPS_LOCSTR";
350+ case SHT_MIPS_LINE:
351+ return "MIPS_LINE";
352+ case SHT_MIPS_RFDESC:
353+ return "MIPS_RFDESC";
354+ case SHT_MIPS_DELTASYM:
355+ return "MIPS_DELTASYM";
356+ case SHT_MIPS_DELTAINST:
357+ return "MIPS_DELTAINST";
358+ case SHT_MIPS_DELTACLASS:
359+ return "MIPS_DELTACLASS";
360+ case SHT_MIPS_DWARF:
361+ return "MIPS_DWARF";
362+ case SHT_MIPS_DELTADECL:
363+ return "MIPS_DELTADECL";
364+ case SHT_MIPS_SYMBOL_LIB:
365+ return "MIPS_SYMBOL_LIB";
366+ case SHT_MIPS_EVENTS:
367+ return "MIPS_EVENTS";
368+ case SHT_MIPS_TRANSLATE:
369+ return "MIPS_TRANSLATE";
370+ case SHT_MIPS_PIXIE:
371+ return "MIPS_PIXIE";
372+ case SHT_MIPS_XLATE:
373+ return "MIPS_XLATE";
374+ case SHT_MIPS_XLATE_DEBUG:
375+ return "MIPS_XLATE_DEBUG";
376+ case SHT_MIPS_WHIRL:
377+ return "MIPS_WHIRL";
378+ case SHT_MIPS_EH_REGION:
379+ return "MIPS_EH_REGION";
380+ case SHT_MIPS_XLATE_OLD:
381+ return "MIPS_XLATE_OLD";
382+ case SHT_MIPS_PDR_EXCEPTION:
383+ return "MIPS_PDR_EXCEPTION";
384+ case SHT_MIPS_ABIFLAGS:
385+ return "MIPS_ABIFLAGS";
386+ case SHT_MIPS_XHASH:
387+ return "MIPS_XHASH";
388+ default:
389+ break;
390+ }
391+ return NULL;
392+}
393+
394+bool
395+mips_check_reloc_target_type (Ebl *ebl __attribute__ ((unused)), Elf64_Word sh_type)
396+{
397+ return (sh_type == SHT_MIPS_DWARF);
398+}
399+
400+/* Check whether given symbol's st_value and st_size are OK despite failing
401+ normal checks. */
402+bool
403+mips_check_special_symbol (Elf *elf,
404+ const GElf_Sym *sym __attribute__ ((unused)),
405+ const char *name __attribute__ ((unused)),
406+ const GElf_Shdr *destshdr)
407+{
408+ size_t shstrndx;
409+ if (elf_getshdrstrndx (elf, &shstrndx) != 0)
410+ return false;
411+ const char *sname = elf_strptr (elf, shstrndx, destshdr->sh_name);
412+ if (sname == NULL)
413+ return false;
414+ return (strcmp (sname, ".got") == 0 || strcmp (sname, ".bss") == 0);
415+}
416+
417+/* Check whether SHF_MASKPROC flags are valid. */
418+bool
419+mips_machine_section_flag_check (GElf_Xword sh_flags)
420+{
421+ return ((sh_flags &~ (SHF_MIPS_GPREL |
422+ SHF_MIPS_MERGE |
423+ SHF_MIPS_ADDR |
424+ SHF_MIPS_STRINGS |
425+ SHF_MIPS_NOSTRIP |
426+ SHF_MIPS_LOCAL |
427+ SHF_MIPS_NAMES |
428+ SHF_MIPS_NODUPE)) == 0);
429+}
430+
431+/* Check whether machine flags are valid. */
432+bool
433+mips_machine_flag_check (GElf_Word flags)
434+{
435+ if ((flags &~ (EF_MIPS_NOREORDER |
436+ EF_MIPS_PIC |
437+ EF_MIPS_CPIC |
438+ EF_MIPS_UCODE |
439+ EF_MIPS_ABI2 |
440+ EF_MIPS_OPTIONS_FIRST |
441+ EF_MIPS_32BITMODE |
442+ EF_MIPS_NAN2008 |
443+ EF_MIPS_FP64 |
444+ EF_MIPS_ARCH_ASE_MDMX |
445+ EF_MIPS_ARCH_ASE_M16 |
446+ EF_MIPS_ARCH_ASE_MICROMIPS)) == 0)
447+ return false;
448+
449+ switch(flags & EF_MIPS_MACH)
450+ {
451+ case EF_MIPS_MACH_3900:
452+ case EF_MIPS_MACH_4010:
453+ case EF_MIPS_MACH_4100:
454+ case EF_MIPS_MACH_4111:
455+ case EF_MIPS_MACH_4120:
456+ case EF_MIPS_MACH_4650:
457+ case EF_MIPS_MACH_5400:
458+ case EF_MIPS_MACH_5500:
459+ case EF_MIPS_MACH_5900:
460+ case EF_MIPS_MACH_SB1:
461+ case EF_MIPS_MACH_9000:
462+ case EF_MIPS_MACH_LS2E:
463+ case EF_MIPS_MACH_LS2F:
464+ case EF_MIPS_MACH_GS464:
465+ case EF_MIPS_MACH_GS464E:
466+ case EF_MIPS_MACH_GS264E:
467+ case EF_MIPS_MACH_OCTEON:
468+ case EF_MIPS_MACH_OCTEON2:
469+ case EF_MIPS_MACH_OCTEON3:
470+ case EF_MIPS_MACH_XLR:
471+ case EF_MIPS_MACH_IAMR2:
472+ case 0:
473+ break;
474+ default:
475+ return false;
476+ }
477+
478+ switch ((flags & EF_MIPS_ABI))
479+ {
480+ case EF_MIPS_ABI_O32:
481+ case EF_MIPS_ABI_O64:
482+ case EF_MIPS_ABI_EABI32:
483+ case EF_MIPS_ABI_EABI64:
484+ case 0:
485+ break;
486+ default:
487+ return false;
488+ }
489+
490+ switch ((flags & EF_MIPS_ARCH))
491+ {
492+ case EF_MIPS_ARCH_1:
493+ case EF_MIPS_ARCH_2:
494+ case EF_MIPS_ARCH_3:
495+ case EF_MIPS_ARCH_4:
496+ case EF_MIPS_ARCH_5:
497+ case EF_MIPS_ARCH_32:
498+ case EF_MIPS_ARCH_32R2:
499+ case EF_MIPS_ARCH_32R6:
500+ case EF_MIPS_ARCH_64:
501+ case EF_MIPS_ARCH_64R2:
502+ case EF_MIPS_ARCH_64R6:
503+ return true;
504+ default:
505+ return false;
506+ }
507+ return false;
508+}
509+
510+/* copy binutils-2.34/binutils/readelf.c get_machine_flags */
511+const char *
512+mips_machine_flag_name (Elf64_Word orig __attribute__ ((unused)), Elf64_Word *flagref)
513+{
514+ if (*flagref & EF_MIPS_NOREORDER)
515+ {
516+ *flagref &= ~((Elf64_Word) EF_MIPS_NOREORDER);
517+ return "noreorder";
518+ }
519+
520+ if (*flagref & EF_MIPS_PIC)
521+ {
522+ *flagref &= ~((Elf64_Word) EF_MIPS_PIC);
523+ return "pic";
524+ }
525+
526+ if (*flagref & EF_MIPS_CPIC)
527+ {
528+ *flagref &= ~((Elf64_Word) EF_MIPS_CPIC);
529+ return "cpic";
530+ }
531+
532+ if (*flagref & EF_MIPS_UCODE)
533+ {
534+ *flagref &= ~((Elf64_Word) EF_MIPS_UCODE);
535+ return "ugen_reserved";
536+ }
537+
538+ if (*flagref & EF_MIPS_ABI2)
539+ {
540+ *flagref &= ~((Elf64_Word) EF_MIPS_ABI2);
541+ return "abi2";
542+ }
543+
544+ if (*flagref & EF_MIPS_OPTIONS_FIRST)
545+ {
546+ *flagref &= ~((Elf64_Word) EF_MIPS_OPTIONS_FIRST);
547+ return "odk first";
548+ }
549+
550+ if (*flagref & EF_MIPS_32BITMODE)
551+ {
552+ *flagref &= ~((Elf64_Word) EF_MIPS_32BITMODE);
553+ return "32bitmode";
554+ }
555+
556+ if (*flagref & EF_MIPS_NAN2008)
557+ {
558+ *flagref &= ~((Elf64_Word) EF_MIPS_NAN2008);
559+ return "nan2008";
560+ }
561+
562+ if (*flagref & EF_MIPS_FP64)
563+ {
564+ *flagref &= ~((Elf64_Word) EF_MIPS_FP64);
565+ return "fp64";
566+ }
567+
568+ switch (*flagref & EF_MIPS_MACH)
569+ {
570+ case EF_MIPS_MACH_3900:
571+ *flagref &= ~((Elf64_Word) EF_MIPS_MACH_3900);
572+ return "3900";
573+ case EF_MIPS_MACH_4010:
574+ *flagref &= ~((Elf64_Word) EF_MIPS_MACH_4010);
575+ return "4010";
576+ case EF_MIPS_MACH_4100:
577+ *flagref &= ~((Elf64_Word) EF_MIPS_MACH_4100);
578+ return "4100";
579+ case EF_MIPS_MACH_4111:
580+ *flagref &= ~((Elf64_Word) EF_MIPS_MACH_4111);
581+ return "4111";
582+ case EF_MIPS_MACH_4120:
583+ *flagref &= ~((Elf64_Word) EF_MIPS_MACH_4120);
584+ return "4120";
585+ case EF_MIPS_MACH_4650:
586+ *flagref &= ~((Elf64_Word) EF_MIPS_MACH_4650);
587+ return "4650";
588+ case EF_MIPS_MACH_5400:
589+ *flagref &= ~((Elf64_Word) EF_MIPS_MACH_5400);
590+ return "5400";
591+ case EF_MIPS_MACH_5500:
592+ *flagref &= ~((Elf64_Word) EF_MIPS_MACH_5500);
593+ return "5500";
594+ case EF_MIPS_MACH_5900:
595+ *flagref &= ~((Elf64_Word) EF_MIPS_MACH_5900);
596+ return "5900";
597+ case EF_MIPS_MACH_SB1:
598+ *flagref &= ~((Elf64_Word) EF_MIPS_MACH_SB1);
599+ return "sb1";
600+ case EF_MIPS_MACH_9000:
601+ *flagref &= ~((Elf64_Word) EF_MIPS_MACH_9000);
602+ return "9000";
603+ case EF_MIPS_MACH_LS2E:
604+ *flagref &= ~((Elf64_Word) EF_MIPS_MACH_LS2E);
605+ return "loongson-2e";
606+ case EF_MIPS_MACH_LS2F:
607+ *flagref &= ~((Elf64_Word) EF_MIPS_MACH_LS2F);
608+ return "loongson-2f";
609+ case EF_MIPS_MACH_GS464:
610+ *flagref &= ~((Elf64_Word) EF_MIPS_MACH_GS464);
611+ return "gs464";
612+ case EF_MIPS_MACH_GS464E:
613+ *flagref &= ~((Elf64_Word) EF_MIPS_MACH_GS464E);
614+ return "gs464e";
615+ case EF_MIPS_MACH_GS264E:
616+ *flagref &= ~((Elf64_Word) EF_MIPS_MACH_GS264E);
617+ return "gs264e";
618+ case EF_MIPS_MACH_OCTEON:
619+ *flagref &= ~((Elf64_Word) EF_MIPS_MACH_OCTEON);
620+ return "octeon";
621+ case EF_MIPS_MACH_OCTEON2:
622+ *flagref &= ~((Elf64_Word) EF_MIPS_MACH_OCTEON2);
623+ return "octeon2";
624+ case EF_MIPS_MACH_OCTEON3:
625+ *flagref &= ~((Elf64_Word) EF_MIPS_MACH_OCTEON3);
626+ return "octeon3";
627+ case EF_MIPS_MACH_XLR:
628+ *flagref &= ~((Elf64_Word) EF_MIPS_MACH_XLR);
629+ return "xlr";
630+ case EF_MIPS_MACH_IAMR2:
631+ *flagref &= ~((Elf64_Word) EF_MIPS_MACH_IAMR2);
632+ return "interaptiv-mr2";
633+ case 0:
634+ /* We simply ignore the field in this case to avoid confusion:
635+ MIPS ELF does not specify EF_MIPS_MACH, it is a GNU
636+ extension. */
637+ break;
638+ default:
639+ *flagref &= ~((Elf64_Word) EF_MIPS_MACH);
640+ return "unknown CPU";
641+ }
642+ switch (*flagref & EF_MIPS_ABI)
643+ {
644+ case EF_MIPS_ABI_O32:
645+ *flagref &= ~((Elf64_Word) EF_MIPS_ABI_O32);
646+ return "o32";
647+ case EF_MIPS_ABI_O64:
648+ *flagref &= ~((Elf64_Word) EF_MIPS_ABI_O64);
649+ return "o64";
650+ case EF_MIPS_ABI_EABI32:
651+ *flagref &= ~((Elf64_Word) EF_MIPS_ABI_EABI32);
652+ return "eabi32";
653+ case EF_MIPS_ABI_EABI64:
654+ *flagref &= ~((Elf64_Word) EF_MIPS_ABI_EABI64);
655+ return "eabi64";
656+ case 0:
657+ /* We simply ignore the field in this case to avoid confusion:
658+ MIPS ELF does not specify EF_MIPS_ABI, it is a GNU extension.
659+ This means it is likely to be an o32 file, but not for
660+ sure. */
661+ break;
662+ default:
663+ *flagref &= ~((Elf64_Word) EF_MIPS_ABI);
664+ return "unknown ABI";
665+ }
666+
667+ if (*flagref & EF_MIPS_ARCH_ASE_MDMX)
668+ {
669+ *flagref &= ~((Elf64_Word) EF_MIPS_ARCH_ASE_MDMX);
670+ return "mdmx";
671+ }
672+
673+ if (*flagref & EF_MIPS_ARCH_ASE_M16)
674+ {
675+ *flagref &= ~((Elf64_Word) EF_MIPS_ARCH_ASE_M16);
676+ return "mips16";
677+ }
678+
679+ if (*flagref & EF_MIPS_ARCH_ASE_MICROMIPS)
680+ {
681+ *flagref &= ~((Elf64_Word) EF_MIPS_ARCH_ASE_MICROMIPS);
682+ return "micromips";
683+ }
684+
685+ switch (*flagref & EF_MIPS_ARCH)
686+ {
687+ case EF_MIPS_ARCH_1:
688+ *flagref &= ~((Elf64_Word) EF_MIPS_ARCH_1);
689+ return "mips1";
690+ case EF_MIPS_ARCH_2:
691+ *flagref &= ~((Elf64_Word) EF_MIPS_ARCH_2);
692+ return "mips2";
693+ case EF_MIPS_ARCH_3:
694+ *flagref &= ~((Elf64_Word) EF_MIPS_ARCH_3);
695+ return "mips3";
696+ case EF_MIPS_ARCH_4:
697+ *flagref &= ~((Elf64_Word) EF_MIPS_ARCH_4);
698+ return "mips4";
699+ case EF_MIPS_ARCH_5:
700+ *flagref &= ~((Elf64_Word) EF_MIPS_ARCH_5);
701+ return "mips5";
702+ case EF_MIPS_ARCH_32:
703+ *flagref &= ~((Elf64_Word) EF_MIPS_ARCH_32);
704+ return "mips32";
705+ case EF_MIPS_ARCH_32R2:
706+ *flagref &= ~((Elf64_Word) EF_MIPS_ARCH_32R2);
707+ return "mips32r2";
708+ case EF_MIPS_ARCH_32R6:
709+ *flagref &= ~((Elf64_Word) EF_MIPS_ARCH_32R6);
710+ return "mips32r6";
711+ case EF_MIPS_ARCH_64:
712+ *flagref &= ~((Elf64_Word) EF_MIPS_ARCH_64);
713+ return "mips64";
714+ case EF_MIPS_ARCH_64R2:
715+ *flagref &= ~((Elf64_Word) EF_MIPS_ARCH_64R2);
716+ return "mips64r2";
717+ case EF_MIPS_ARCH_64R6:
718+ *flagref &= ~((Elf64_Word) EF_MIPS_ARCH_64R6);
719+ return "mips64r6";
720+ default:
721+ *flagref &= ~((Elf64_Word) EF_MIPS_ARCH);
722+ return "unknown ISA";
723+ }
724+ return NULL;
725+}
726+
727+/* copy binutils-2.34/binutils/readelf.c get_mips_segment_type */
728+const char *
729+mips_segment_type_name (int segment, char *buf __attribute__ ((unused)),
730+ size_t len __attribute__ ((unused)))
731+{
732+ switch (segment)
733+ {
734+ case PT_MIPS_REGINFO:
735+ return "REGINFO";
736+ case PT_MIPS_RTPROC:
737+ return "RTPROC";
738+ case PT_MIPS_OPTIONS:
739+ return "OPTIONS";
740+ case PT_MIPS_ABIFLAGS:
741+ return "ABIFLAGS";
742+ default:
743+ return NULL;
744+ }
745+}
746+
747+bool
748+mips_dynamic_tag_check (int64_t tag)
749+{
750+ return ((tag &~ (DT_MIPS_RLD_VERSION
751+ | DT_MIPS_TIME_STAMP
752+ | DT_MIPS_ICHECKSUM
753+ | DT_MIPS_IVERSION
754+ | DT_MIPS_FLAGS
755+ | DT_MIPS_BASE_ADDRESS
756+ | DT_MIPS_MSYM
757+ | DT_MIPS_CONFLICT
758+ | DT_MIPS_LIBLIST
759+ | DT_MIPS_LOCAL_GOTNO
760+ | DT_MIPS_CONFLICTNO
761+ | DT_MIPS_LIBLISTNO
762+ | DT_MIPS_SYMTABNO
763+ | DT_MIPS_UNREFEXTNO
764+ | DT_MIPS_GOTSYM
765+ | DT_MIPS_HIPAGENO
766+ | DT_MIPS_RLD_MAP
767+ | DT_MIPS_DELTA_CLASS
768+ | DT_MIPS_DELTA_CLASS_NO
769+ | DT_MIPS_DELTA_INSTANCE
770+ | DT_MIPS_DELTA_INSTANCE_NO
771+ | DT_MIPS_DELTA_RELOC
772+ | DT_MIPS_DELTA_RELOC_NO
773+ | DT_MIPS_DELTA_SYM
774+ | DT_MIPS_DELTA_SYM_NO
775+ | DT_MIPS_DELTA_CLASSSYM
776+ | DT_MIPS_DELTA_CLASSSYM_NO
777+ | DT_MIPS_CXX_FLAGS
778+ | DT_MIPS_PIXIE_INIT
779+ | DT_MIPS_SYMBOL_LIB
780+ | DT_MIPS_LOCALPAGE_GOTIDX
781+ | DT_MIPS_LOCAL_GOTIDX
782+ | DT_MIPS_HIDDEN_GOTIDX
783+ | DT_MIPS_PROTECTED_GOTIDX
784+ | DT_MIPS_OPTIONS
785+ | DT_MIPS_INTERFACE
786+ | DT_MIPS_DYNSTR_ALIGN
787+ | DT_MIPS_INTERFACE_SIZE
788+ | DT_MIPS_RLD_TEXT_RESOLVE_ADDR
789+ | DT_MIPS_PERF_SUFFIX
790+ | DT_MIPS_COMPACT_SIZE
791+ | DT_MIPS_GP_VALUE
792+ | DT_MIPS_AUX_DYNAMIC
793+ | DT_MIPS_PLTGOT
794+ | DT_MIPS_RWPLT
795+ | DT_MIPS_RLD_MAP_REL
796+ | DT_MIPS_XHASH)) == 0);
797+}
798+
799+/* copy binutils-2.34/binutils/readelf.c get_mips_dynamic_type*/
800+const char *
801+mips_dynamic_tag_name (int64_t tag, char *buf __attribute__ ((unused)),
802+ size_t len __attribute__ ((unused)))
803+{
804+ switch (tag)
805+ {
806+ case DT_MIPS_RLD_VERSION:
807+ return "MIPS_RLD_VERSION";
808+ case DT_MIPS_TIME_STAMP:
809+ return "MIPS_TIME_STAMP";
810+ case DT_MIPS_ICHECKSUM:
811+ return "MIPS_ICHECKSUM";
812+ case DT_MIPS_IVERSION:
813+ return "MIPS_IVERSION";
814+ case DT_MIPS_FLAGS:
815+ return "MIPS_FLAGS";
816+ case DT_MIPS_BASE_ADDRESS:
817+ return "MIPS_BASE_ADDRESS";
818+ case DT_MIPS_MSYM:
819+ return "MIPS_MSYM";
820+ case DT_MIPS_CONFLICT:
821+ return "MIPS_CONFLICT";
822+ case DT_MIPS_LIBLIST:
823+ return "MIPS_LIBLIST";
824+ case DT_MIPS_LOCAL_GOTNO:
825+ return "MIPS_LOCAL_GOTNO";
826+ case DT_MIPS_CONFLICTNO:
827+ return "MIPS_CONFLICTNO";
828+ case DT_MIPS_LIBLISTNO:
829+ return "MIPS_LIBLISTNO";
830+ case DT_MIPS_SYMTABNO:
831+ return "MIPS_SYMTABNO";
832+ case DT_MIPS_UNREFEXTNO:
833+ return "MIPS_UNREFEXTNO";
834+ case DT_MIPS_GOTSYM:
835+ return "MIPS_GOTSYM";
836+ case DT_MIPS_HIPAGENO:
837+ return "MIPS_HIPAGENO";
838+ case DT_MIPS_RLD_MAP:
839+ return "MIPS_RLD_MAP";
840+ case DT_MIPS_RLD_MAP_REL:
841+ return "MIPS_RLD_MAP_REL";
842+ case DT_MIPS_DELTA_CLASS:
843+ return "MIPS_DELTA_CLASS";
844+ case DT_MIPS_DELTA_CLASS_NO:
845+ return "MIPS_DELTA_CLASS_NO";
846+ case DT_MIPS_DELTA_INSTANCE:
847+ return "MIPS_DELTA_INSTANCE";
848+ case DT_MIPS_DELTA_INSTANCE_NO:
849+ return "MIPS_DELTA_INSTANCE_NO";
850+ case DT_MIPS_DELTA_RELOC:
851+ return "MIPS_DELTA_RELOC";
852+ case DT_MIPS_DELTA_RELOC_NO:
853+ return "MIPS_DELTA_RELOC_NO";
854+ case DT_MIPS_DELTA_SYM:
855+ return "MIPS_DELTA_SYM";
856+ case DT_MIPS_DELTA_SYM_NO:
857+ return "MIPS_DELTA_SYM_NO";
858+ case DT_MIPS_DELTA_CLASSSYM:
859+ return "MIPS_DELTA_CLASSSYM";
860+ case DT_MIPS_DELTA_CLASSSYM_NO:
861+ return "MIPS_DELTA_CLASSSYM_NO";
862+ case DT_MIPS_CXX_FLAGS:
863+ return "MIPS_CXX_FLAGS";
864+ case DT_MIPS_PIXIE_INIT:
865+ return "MIPS_PIXIE_INIT";
866+ case DT_MIPS_SYMBOL_LIB:
867+ return "MIPS_SYMBOL_LIB";
868+ case DT_MIPS_LOCALPAGE_GOTIDX:
869+ return "MIPS_LOCALPAGE_GOTIDX";
870+ case DT_MIPS_LOCAL_GOTIDX:
871+ return "MIPS_LOCAL_GOTIDX";
872+ case DT_MIPS_HIDDEN_GOTIDX:
873+ return "MIPS_HIDDEN_GOTIDX";
874+ case DT_MIPS_PROTECTED_GOTIDX:
875+ return "MIPS_PROTECTED_GOTIDX";
876+ case DT_MIPS_OPTIONS:
877+ return "MIPS_OPTIONS";
878+ case DT_MIPS_INTERFACE:
879+ return "MIPS_INTERFACE";
880+ case DT_MIPS_DYNSTR_ALIGN:
881+ return "MIPS_DYNSTR_ALIGN";
882+ case DT_MIPS_INTERFACE_SIZE:
883+ return "MIPS_INTERFACE_SIZE";
884+ case DT_MIPS_RLD_TEXT_RESOLVE_ADDR:
885+ return "MIPS_RLD_TEXT_RESOLVE_ADDR";
886+ case DT_MIPS_PERF_SUFFIX:
887+ return "MIPS_PERF_SUFFIX";
888+ case DT_MIPS_COMPACT_SIZE:
889+ return "MIPS_COMPACT_SIZE";
890+ case DT_MIPS_GP_VALUE:
891+ return "MIPS_GP_VALUE";
892+ case DT_MIPS_AUX_DYNAMIC:
893+ return "MIPS_AUX_DYNAMIC";
894+ case DT_MIPS_PLTGOT:
895+ return "MIPS_PLTGOT";
896+ case DT_MIPS_RWPLT:
897+ return "MIPS_RWPLT";
898+ case DT_MIPS_XHASH:
899+ return "MIPS_XHASH";
900+ default:
901+ return NULL;
902+ }
903+ return NULL;
904+}
905--- a/libebl/eblopenbackend.c
906+++ b/libebl/eblopenbackend.c
907@@ -57,6 +57,7 @@ Ebl *riscv_init (Elf *, GElf_Half, Ebl *
908 Ebl *csky_init (Elf *, GElf_Half, Ebl *);
909 Ebl *loongarch_init (Elf *, GElf_Half, Ebl *);
910 Ebl *arc_init (Elf *, GElf_Half, Ebl *);
911+Ebl *mips_init (Elf *, GElf_Half, Ebl *);
912
913 /* This table should contain the complete list of architectures as far
914 as the ELF specification is concerned. */
915@@ -154,6 +155,7 @@ static const struct
916 { csky_init, "elf_csky", "csky", 4, EM_CSKY, ELFCLASS32, ELFDATA2LSB },
917 { loongarch_init, "elf_loongarch", "loongarch", 9, EM_LOONGARCH, ELFCLASS64, ELFDATA2LSB },
918 { arc_init, "elf_arc", "arc", 3, EM_ARCV2, ELFCLASS32, ELFDATA2LSB },
919+ { mips_init, "elf_mips", "mips", 4, EM_MIPS, 0, 0 },
920 };
921 #define nmachines (sizeof (machines) / sizeof (machines[0]))
922
923--- a/libelf/libelfP.h
924+++ b/libelf/libelfP.h
925@@ -617,4 +617,8 @@ extern void __libelf_reset_rawdata (Elf_
926 #define INVALID_NDX(ndx, type, data) \
927 unlikely ((data)->d_size / sizeof (type) <= (unsigned int) (ndx))
928
929+#define ELF64_MIPS_R_TYPE1(i) ((i) & 0xff)
930+#define ELF64_MIPS_R_TYPE2(i) (((i) >> 8) & 0xff)
931+#define ELF64_MIPS_R_TYPE3(i) (((i) >> 16) & 0xff)
932+#define is_debug_section_type(type) (type == SHT_PROGBITS || type == SHT_MIPS_DWARF)
933 #endif /* libelfP.h */
934--- /dev/null
935+++ b/backends/mips_cfi.c
936@@ -0,0 +1,68 @@
937+/* MIPS ABI-specified defaults for DWARF CFI.
938+ Copyright (C) 2009 Red Hat, Inc.
939+ Copyright (C) 2024 CIP United Inc.
940+ This file is part of elfutils.
941+
942+ This file is free software; you can redistribute it and/or modify
943+ it under the terms of either
944+
945+ * the GNU Lesser General Public License as published by the Free
946+ Software Foundation; either version 3 of the License, or (at
947+ your option) any later version
948+
949+ or
950+
951+ * the GNU General Public License as published by the Free
952+ Software Foundation; either version 2 of the License, or (at
953+ your option) any later version
954+
955+ or both in parallel, as here.
956+
957+ elfutils is distributed in the hope that it will be useful, but
958+ WITHOUT ANY WARRANTY; without even the implied warranty of
959+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
960+ General Public License for more details.
961+
962+ You should have received copies of the GNU General Public License and
963+ the GNU Lesser General Public License along with this program. If
964+ not, see <http://www.gnu.org/licenses/>. */
965+
966+#ifdef HAVE_CONFIG_H
967+# include <config.h>
968+#endif
969+
970+#include <dwarf.h>
971+
972+#define BACKEND mips_
973+#include "libebl_CPU.h"
974+
975+int
976+mips_abi_cfi (Ebl *ebl __attribute__ ((unused)), Dwarf_CIE *abi_info)
977+{
978+ static const uint8_t abi_cfi[] =
979+ {
980+ DW_CFA_def_cfa, ULEB128_7 (31), ULEB128_7 (0),
981+ /* Callee-saved regs. */
982+ DW_CFA_same_value, ULEB128_7 (16), /* s0 */
983+ DW_CFA_same_value, ULEB128_7 (17), /* s1 */
984+ DW_CFA_same_value, ULEB128_7 (18), /* s2 */
985+ DW_CFA_same_value, ULEB128_7 (19), /* s3 */
986+ DW_CFA_same_value, ULEB128_7 (20), /* s4 */
987+ DW_CFA_same_value, ULEB128_7 (21), /* s5 */
988+ DW_CFA_same_value, ULEB128_7 (22), /* s6 */
989+ DW_CFA_same_value, ULEB128_7 (23), /* s7 */
990+ DW_CFA_same_value, ULEB128_7 (28), /* gp */
991+ DW_CFA_same_value, ULEB128_7 (29), /* sp */
992+ DW_CFA_same_value, ULEB128_7 (30), /* fp */
993+
994+ DW_CFA_val_offset, ULEB128_7 (29), ULEB128_7 (0),
995+ };
996+
997+ abi_info->initial_instructions = abi_cfi;
998+ abi_info->initial_instructions_end = &abi_cfi[sizeof abi_cfi];
999+ abi_info->data_alignment_factor = 8;
1000+
1001+ abi_info->return_address_register = 31; /* %ra */
1002+
1003+ return 0;
1004+}
1005--- /dev/null
1006+++ b/backends/mips_initreg.c
1007@@ -0,0 +1,61 @@
1008+/* Fetch live process registers from TID.
1009+ Copyright (C) 2024 CIP United Inc.
1010+ This file is part of elfutils.
1011+
1012+ This file is free software; you can redistribute it and/or modify
1013+ it under the terms of either
1014+
1015+ * the GNU Lesser General Public License as published by the Free
1016+ Software Foundation; either version 3 of the License, or (at
1017+ your option) any later version
1018+
1019+ or
1020+
1021+ * the GNU General Public License as published by the Free
1022+ Software Foundation; either version 2 of the License, or (at
1023+ your option) any later version
1024+
1025+ or both in parallel, as here.
1026+
1027+ elfutils is distributed in the hope that it will be useful, but
1028+ WITHOUT ANY WARRANTY; without even the implied warranty of
1029+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1030+ General Public License for more details.
1031+
1032+ You should have received copies of the GNU General Public License and
1033+ the GNU Lesser General Public License along with this program. If
1034+ not, see <http://www.gnu.org/licenses/>. */
1035+
1036+#ifdef HAVE_CONFIG_H
1037+# include <config.h>
1038+#endif
1039+
1040+#include <stdlib.h>
1041+#if (defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__)) && defined(__linux__)
1042+# include <sys/user.h>
1043+# include <sys/ptrace.h>
1044+#include <asm/ptrace.h>
1045+#endif
1046+
1047+#define BACKEND mips_
1048+#include "libebl_CPU.h"
1049+
1050+
1051+bool
1052+mips_set_initial_registers_tid (pid_t tid __attribute__ ((unused)),
1053+ ebl_tid_registers_t *setfunc __attribute__ ((unused)),
1054+ void *arg __attribute__ ((unused)))
1055+{
1056+#if (!defined(mips) && !defined(__mips) && !defined(__mips__) && !defined(MIPS) && !defined(__MIPS__)) || !defined(__linux__)
1057+ return false;
1058+#else /* __mips__ */
1059+/* For PTRACE_GETREGS */
1060+
1061+ struct pt_regs gregs;
1062+ if (ptrace (PTRACE_GETREGS, tid, 0, &gregs) != 0)
1063+ return false;
1064+ if (! setfunc (-1, 1, (Dwarf_Word *) &gregs.cp0_epc, arg))
1065+ return false;
1066+ return setfunc (0, 32, (Dwarf_Word *) &gregs.regs[0], arg);
1067+#endif /* __mips__ */
1068+}
1069--- /dev/null
1070+++ b/backends/mips_unwind.c
1071@@ -0,0 +1,84 @@
1072+/* Get previous frame state for an existing frame state.
1073+ Copyright (C) 2016 The Qt Company Ltd.
1074+ Copyright (C) 2024 CIP United Inc.
1075+ This file is part of elfutils.
1076+
1077+ This file is free software; you can redistribute it and/or modify
1078+ it under the terms of either
1079+
1080+ * the GNU Lesser General Public License as published by the Free
1081+ Software Foundation; either version 3 of the License, or (at
1082+ your option) any later version
1083+
1084+ or
1085+
1086+ * the GNU General Public License as published by the Free
1087+ Software Foundation; either version 2 of the License, or (at
1088+ your option) any later version
1089+
1090+ or both in parallel, as here.
1091+
1092+ elfutils is distributed in the hope that it will be useful, but
1093+ WITHOUT ANY WARRANTY; without even the implied warranty of
1094+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1095+ General Public License for more details.
1096+
1097+ You should have received copies of the GNU General Public License and
1098+ the GNU Lesser General Public License along with this program. If
1099+ not, see <http://www.gnu.org/licenses/>. */
1100+
1101+#ifdef HAVE_CONFIG_H
1102+# include <config.h>
1103+#endif
1104+
1105+#define BACKEND mips_
1106+#define SP_REG 29
1107+#define FP_REG 30
1108+#define LR_REG 31
1109+#define FP_OFFSET 0
1110+#define LR_OFFSET 8
1111+#define SP_OFFSET 16
1112+
1113+#include "libebl_CPU.h"
1114+
1115+/* There was no CFI. Maybe we happen to have a frame pointer and can unwind from that? */
1116+
1117+bool
1118+EBLHOOK(unwind) (Ebl *ebl __attribute__ ((unused)), Dwarf_Addr pc __attribute__ ((unused)),
1119+ ebl_tid_registers_t *setfunc, ebl_tid_registers_get_t *getfunc,
1120+ ebl_pid_memory_read_t *readfunc, void *arg,
1121+ bool *signal_framep __attribute__ ((unused)))
1122+{
1123+ Dwarf_Word fp, lr, sp;
1124+
1125+ if (!getfunc(LR_REG, 1, &lr, arg))
1126+ return false;
1127+
1128+ if (lr == 0 || !setfunc(-1, 1, &lr, arg))
1129+ return false;
1130+
1131+ if (!getfunc(FP_REG, 1, &fp, arg))
1132+ fp = 0;
1133+
1134+ if (!getfunc(SP_REG, 1, &sp, arg))
1135+ sp = 0;
1136+
1137+ Dwarf_Word newLr, newFp, newSp;
1138+
1139+ if (!readfunc(fp + LR_OFFSET, &newLr, arg))
1140+ newLr = 0;
1141+
1142+ if (!readfunc(fp + FP_OFFSET, &newFp, arg))
1143+ newFp = 0;
1144+
1145+ newSp = fp + SP_OFFSET;
1146+
1147+ // These are not fatal if they don't work. They will just prevent unwinding at the next frame.
1148+ setfunc(LR_REG, 1, &newLr, arg);
1149+ setfunc(FP_REG, 1, &newFp, arg);
1150+ setfunc(SP_REG, 1, &newSp, arg);
1151+
1152+ // If the fp is invalid, we might still have a valid lr.
1153+ // But if the fp is valid, then the stack should be moving in the right direction.
1154+ return fp == 0 || newSp > sp;
1155+}
1156--- /dev/null
1157+++ b/backends/mips_corenote.c
1158@@ -0,0 +1,104 @@
1159+/* MIPS specific core note handling.
1160+ Copyright (C) 2024 CIP United Inc.
1161+ This file is part of elfutils.
1162+
1163+ This file is free software; you can redistribute it and/or modify
1164+ it under the terms of either
1165+
1166+ * the GNU Lesser General Public License as published by the Free
1167+ Software Foundation; either version 3 of the License, or (at
1168+ your option) any later version
1169+
1170+ or
1171+
1172+ * the GNU General Public License as published by the Free
1173+ Software Foundation; either version 2 of the License, or (at
1174+ your option) any later version
1175+
1176+ or both in parallel, as here.
1177+
1178+ elfutils is distributed in the hope that it will be useful, but
1179+ WITHOUT ANY WARRANTY; without even the implied warranty of
1180+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1181+ General Public License for more details.
1182+
1183+ You should have received copies of the GNU General Public License and
1184+ the GNU Lesser General Public License along with this program. If
1185+ not, see <http://www.gnu.org/licenses/>. */
1186+
1187+#ifdef HAVE_CONFIG_H
1188+# include <config.h>
1189+#endif
1190+
1191+#include <elf.h>
1192+#include <inttypes.h>
1193+#include <stddef.h>
1194+#include <stdio.h>
1195+#include <sys/time.h>
1196+#include "libebl_CPU.h"
1197+
1198+#ifndef BITS
1199+# define BITS 32
1200+#define BACKEND mips_
1201+#else
1202+# define BITS 64
1203+# define BACKEND mips64_
1204+#endif
1205+
1206+#define PRSTATUS_REGS_SIZE (45 * (BITS / 8))
1207+static const Ebl_Register_Location prstatus_regs[] =
1208+ {
1209+ { .offset = 0, .regno = 0, .count = (BITS == 32 ? 40 : 34), .bits = BITS },
1210+ { .offset = BITS/8 * (BITS == 32 ? 41 : 35), .regno = (BITS == 32 ? 41 : 35), .count = (BITS == 32 ? 4 : 10), .bits = BITS },
1211+ };
1212+
1213+#define PRSTATUS_REGSET_ITEMS \
1214+ { \
1215+ .name = "pc", .type = ELF_T_ADDR, .format = 'x', \
1216+ .offset = offsetof (struct EBLHOOK(prstatus), pr_reg) + ((BITS/8) * (BITS == 32 ? 40 : 34)), \
1217+ .group = "register", \
1218+ .pc_register = true \
1219+ }
1220+
1221+static const Ebl_Register_Location mips_fpregset_regs[] =
1222+ {
1223+ { .offset = 0, .regno = 38, .count = 32, .bits = 64 }, /* fp0-fp31 */
1224+ };
1225+
1226+static const Ebl_Core_Item mips_fpregset_items[] =
1227+ {
1228+ {
1229+ .name = "fcs", .type = ELF_T_WORD, .format = 'x',
1230+ .offset = 32 * 8, .group = "register"
1231+ },
1232+ {
1233+ .name = "fir", .type = ELF_T_WORD, .format = 'x',
1234+ .offset = 32 * 8 + 4, .group = "register"
1235+ }
1236+ };
1237+
1238+#if BITS == 32
1239+# define ULONG uint32_t
1240+# define ALIGN_ULONG 4
1241+# define TYPE_ULONG ELF_T_WORD
1242+#define TYPE_LONG ELF_T_SWORD
1243+#else
1244+#define ULONG uint64_t
1245+#define ALIGN_ULONG 8
1246+#define TYPE_ULONG ELF_T_XWORD
1247+#define TYPE_LONG ELF_T_SXWORD
1248+#endif
1249+#define PID_T int32_t
1250+#define UID_T uint32_t
1251+#define GID_T uint32_t
1252+#define ALIGN_PID_T 4
1253+#define ALIGN_UID_T 4
1254+#define ALIGN_GID_T 4
1255+#define TYPE_PID_T ELF_T_SWORD
1256+#define TYPE_UID_T ELF_T_WORD
1257+#define TYPE_GID_T ELF_T_WORD
1258+
1259+#define EXTRA_NOTES \
1260+ EXTRA_REGSET_ITEMS (NT_FPREGSET, 32 * 8 + 4 * 2, mips_fpregset_regs, mips_fpregset_items)
1261+
1262+#include "linux-core-note.c"
1263--- /dev/null
1264+++ b/backends/mips_regs.c
1265@@ -0,0 +1,135 @@
1266+/* Register names and numbers for mips DWARF.
1267+ Copyright (C) 2006 Red Hat, Inc.
1268+ Copyright (C) 2024 CIP United Inc.
1269+ This file is part of elfutils.
1270+
1271+ This file is free software; you can redistribute it and/or modify
1272+ it under the terms of either
1273+
1274+ * the GNU Lesser General Public License as published by the Free
1275+ Software Foundation; either version 3 of the License, or (at
1276+ your option) any later version
1277+
1278+ or
1279+
1280+ * the GNU General Public License as published by the Free
1281+ Software Foundation; either version 2 of the License, or (at
1282+ your option) any later version
1283+
1284+ or both in parallel, as here.
1285+
1286+ elfutils is distributed in the hope that it will be useful, but
1287+ WITHOUT ANY WARRANTY; without even the implied warranty of
1288+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1289+ General Public License for more details.
1290+
1291+ You should have received copies of the GNU General Public License and
1292+ the GNU Lesser General Public License along with this program. If
1293+ not, see <http://www.gnu.org/licenses/>. */
1294+
1295+#ifdef HAVE_CONFIG_H
1296+# include <config.h>
1297+#endif
1298+
1299+#include <assert.h>
1300+#include <dwarf.h>
1301+#include <string.h>
1302+
1303+#define BACKEND mips_
1304+#include "libebl_CPU.h"
1305+#include <system.h>
1306+ssize_t
1307+mips_register_info (Ebl *ebl __attribute__ ((unused)),
1308+ int regno, char *name, size_t namelen,
1309+ const char **prefix, const char **setname,
1310+ int *bits, int *type)
1311+{
1312+ if (name == NULL)
1313+ return 72;
1314+
1315+ if (regno < 0 || regno > 71 || namelen < 4)
1316+ return -1;
1317+
1318+ *prefix = "$";
1319+ if (regno < 38)
1320+ {
1321+ *setname = "integer";
1322+ *type = DW_ATE_signed;
1323+ *bits = 32;
1324+ }
1325+ else
1326+ {
1327+ *setname = "FPU";
1328+ *type = DW_ATE_float;
1329+ *bits = 64;
1330+ }
1331+
1332+ if (regno < 32)
1333+ {
1334+ if (regno < 10)
1335+ {
1336+ name[0] = regno + '0';
1337+ namelen = 1;
1338+ }
1339+ else
1340+ {
1341+ name[0] = (regno / 10) + '0';
1342+ name[1] = (regno % 10) + '0';
1343+ namelen = 2;
1344+ }
1345+ if (regno == 28 || regno == 29 || regno == 31)
1346+ *type = DW_ATE_address;
1347+ }
1348+ else if (regno == 32)
1349+ {
1350+ return stpcpy (name, "lo") + 1 - name;
1351+ }
1352+ else if (regno == 33)
1353+ {
1354+ return stpcpy (name, "hi") + 1 - name;
1355+ }
1356+ else if (regno == 34)
1357+ {
1358+ return stpcpy (name, "pc") + 1 - name;
1359+ }
1360+ else if (regno == 35)
1361+ {
1362+ *type = DW_ATE_address;
1363+ return stpcpy (name, "bad") + 1 - name;
1364+ }
1365+ else if (regno == 36)
1366+ {
1367+ return stpcpy (name, "sr") + 1 - name;
1368+ }
1369+ else if (regno == 37)
1370+ {
1371+ *type = DW_ATE_address;
1372+ return stpcpy (name, "cause") + 1 - name;
1373+ }
1374+ else if (regno < 70)
1375+ {
1376+ name[0] = 'f';
1377+ if (regno < 38 + 10)
1378+ {
1379+ name[1] = (regno - 38) + '0';
1380+ namelen = 2;
1381+ }
1382+ else
1383+ {
1384+ name[1] = (regno - 38) / 10 + '0';
1385+ name[2] = (regno - 38) % 10 + '0';
1386+ namelen = 3;
1387+ }
1388+ }
1389+ else if (regno == 70)
1390+ {
1391+ return stpcpy (name, "fsr") + 1 - name;
1392+ }
1393+ else if (regno == 71)
1394+ {
1395+ return stpcpy (name, "fir") + 1 - name;
1396+ }
1397+
1398+ name[namelen++] = '\0';
1399+ return namelen;
1400+}
1401--- /dev/null
1402+++ b/backends/mips_retval.c
1403@@ -0,0 +1,196 @@
1404+/* Function return value location for Linux/mips ABI.
1405+ Copyright (C) 2005 Red Hat, Inc.
1406+ Copyright (C) 2024 CIP United Inc.
1407+ This file is part of elfutils.
1408+
1409+ This file is free software; you can redistribute it and/or modify
1410+ it under the terms of either
1411+
1412+ * the GNU Lesser General Public License as published by the Free
1413+ Software Foundation; either version 3 of the License, or (at
1414+ your option) any later version
1415+
1416+ or
1417+
1418+ * the GNU General Public License as published by the Free
1419+ Software Foundation; either version 2 of the License, or (at
1420+ your option) any later version
1421+
1422+ or both in parallel, as here.
1423+
1424+ elfutils is distributed in the hope that it will be useful, but
1425+ WITHOUT ANY WARRANTY; without even the implied warranty of
1426+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1427+ General Public License for more details.
1428+
1429+ You should have received copies of the GNU General Public License and
1430+ the GNU Lesser General Public License along with this program. If
1431+ not, see <http://www.gnu.org/licenses/>. */
1432+
1433+#ifdef HAVE_CONFIG_H
1434+# include <config.h>
1435+#endif
1436+
1437+#include <assert.h>
1438+#include <dwarf.h>
1439+#include <string.h>
1440+#include <elf.h>
1441+#include <stdio.h>
1442+
1443+#define BACKEND mips_
1444+#include "libebl_CPU.h"
1445+#include "libdwP.h"
1446+#include <stdio.h>
1447+
1448+/* $v0 or pair $v0, $v1 */
1449+static const Dwarf_Op loc_intreg_o32[] =
1450+ {
1451+ { .atom = DW_OP_reg2 }, { .atom = DW_OP_piece, .number = 4 },
1452+ { .atom = DW_OP_reg3 }, { .atom = DW_OP_piece, .number = 4 },
1453+ };
1454+
1455+static const Dwarf_Op loc_intreg[] =
1456+ {
1457+ { .atom = DW_OP_reg2 }, { .atom = DW_OP_piece, .number = 8 },
1458+ { .atom = DW_OP_reg3 }, { .atom = DW_OP_piece, .number = 8 },
1459+ };
1460+#define nloc_intreg 1
1461+#define nloc_intregpair 4
1462+
1463+/* $f0 (float), or pair $f0, $f1 (double).
1464+ * f2/f3 are used for COMPLEX (= 2 doubles) returns in Fortran */
1465+static const Dwarf_Op loc_fpreg_o32[] =
1466+ {
1467+ { .atom = DW_OP_regx, .number = 32 }, { .atom = DW_OP_piece, .number = 4 },
1468+ { .atom = DW_OP_regx, .number = 33 }, { .atom = DW_OP_piece, .number = 4 },
1469+ { .atom = DW_OP_regx, .number = 34 }, { .atom = DW_OP_piece, .number = 4 },
1470+ { .atom = DW_OP_regx, .number = 35 }, { .atom = DW_OP_piece, .number = 4 },
1471+ };
1472+
1473+/* $f0, or pair $f0, $f2. */
1474+static const Dwarf_Op loc_fpreg[] =
1475+ {
1476+ { .atom = DW_OP_regx, .number = 32 }, { .atom = DW_OP_piece, .number = 8 },
1477+ { .atom = DW_OP_regx, .number = 34 }, { .atom = DW_OP_piece, .number = 8 },
1478+ };
1479+#define nloc_fpreg 1
1480+#define nloc_fpregpair 4
1481+#define nloc_fpregquad 8
1482+
1483+/* The return value is a structure and is actually stored in stack space
1484+ passed in a hidden argument by the caller. But, the compiler
1485+ helpfully returns the address of that space in $v0. */
1486+static const Dwarf_Op loc_aggregate[] =
1487+ {
1488+ { .atom = DW_OP_breg2, .number = 0 }
1489+ };
1490+#define nloc_aggregate 1
1491+
1492+int
1493+mips_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
1494+{
1495+ unsigned int regsize = (gelf_getclass (functypedie->cu->dbg->elf) == ELFCLASS32 ) ? 4 : 8;
1496+ if (!regsize)
1497+ return -2;
1498+
1499+ /* Start with the function's type, and get the DW_AT_type attribute,
1500+ which is the type of the return value. */
1501+
1502+ Dwarf_Attribute attr_mem;
1503+ Dwarf_Attribute *attr = dwarf_attr_integrate (functypedie, DW_AT_type, &attr_mem);
1504+ if (attr == NULL)
1505+ /* The function has no return value, like a `void' function in C. */
1506+ return 0;
1507+
1508+ Dwarf_Die die_mem;
1509+ Dwarf_Die *typedie = dwarf_formref_die (attr, &die_mem);
1510+ int tag = dwarf_tag (typedie);
1511+
1512+ /* Follow typedefs and qualifiers to get to the actual type. */
1513+ while (tag == DW_TAG_typedef
1514+ || tag == DW_TAG_const_type || tag == DW_TAG_volatile_type
1515+ || tag == DW_TAG_restrict_type)
1516+ {
1517+ attr = dwarf_attr_integrate (typedie, DW_AT_type, &attr_mem);
1518+ typedie = dwarf_formref_die (attr, &die_mem);
1519+ tag = dwarf_tag (typedie);
1520+ }
1521+
1522+ switch (tag)
1523+ {
1524+ case -1:
1525+ return -1;
1526+
1527+ case DW_TAG_subrange_type:
1528+ if (! dwarf_hasattr_integrate (typedie, DW_AT_byte_size))
1529+ {
1530+ attr = dwarf_attr_integrate (typedie, DW_AT_type, &attr_mem);
1531+ typedie = dwarf_formref_die (attr, &die_mem);
1532+ tag = dwarf_tag (typedie);
1533+ }
1534+ /* Fall through. */
1535+ FALLTHROUGH;
1536+
1537+ case DW_TAG_base_type:
1538+ case DW_TAG_enumeration_type:
1539+ CASE_POINTER:
1540+ {
1541+ Dwarf_Word size;
1542+ if (dwarf_formudata (dwarf_attr_integrate (typedie, DW_AT_byte_size,
1543+ &attr_mem), &size) != 0)
1544+ {
1545+ if (dwarf_is_pointer (tag))
1546+ size = regsize;
1547+ else
1548+ return -1;
1549+ }
1550+ if (tag == DW_TAG_base_type)
1551+ {
1552+ Dwarf_Word encoding;
1553+ if (dwarf_formudata (dwarf_attr_integrate (typedie, DW_AT_encoding,
1554+ &attr_mem), &encoding) != 0)
1555+ return -1;
1556+
1557+#define ARCH_LOC(loc, regsize) ((regsize) == 4 ? (loc ## _o32) : (loc))
1558+
1559+ if (encoding == DW_ATE_float)
1560+ {
1561+ *locp = ARCH_LOC(loc_fpreg, regsize);
1562+ if (size <= regsize)
1563+ return nloc_fpreg;
1564+
1565+ if (size <= 2*regsize)
1566+ return nloc_fpregpair;
1567+
1568+ if (size <= 4*regsize)
1569+ return nloc_fpregquad;
1570+
1571+ goto aggregate;
1572+ }
1573+ }
1574+ *locp = ARCH_LOC(loc_intreg, regsize);
1575+ if (size <= regsize)
1576+ return nloc_intreg;
1577+ if (size <= 2*regsize)
1578+ return nloc_intregpair;
1579+
1580+ /* Else fall through. Shouldn't happen though (at least with gcc) */
1581+ }
1582+ FALLTHROUGH;
1583+
1584+ case DW_TAG_structure_type:
1585+ case DW_TAG_class_type:
1586+ case DW_TAG_union_type:
1587+ case DW_TAG_array_type:
1588+ aggregate:
1589+ *locp = loc_aggregate;
1590+ return nloc_aggregate;
1591+ case DW_TAG_unspecified_type:
1592+ return 0;
1593+ }
1594+
1595+ /* XXX We don't have a good way to return specific errors from ebl calls.
1596+ This value means we do not understand the type, but it is well-formed
1597+ DWARF and might be valid. */
1598+ return -2;
1599+}
1600--- a/libelf/elf_getdata.c
1601+++ b/libelf/elf_getdata.c
1602@@ -135,6 +135,119 @@ __libelf_data_type (GElf_Ehdr *ehdr, int
1603
1604 /* Convert the data in the current section. */
1605 static void
1606+convert_data_for_mips64el (Elf_Scn *scn, int eclass,
1607+ int data, size_t size, Elf_Type type)
1608+{
1609+ /* Do we need to convert the data and/or adjust for alignment? */
1610+ if (data == MY_ELFDATA || type == ELF_T_BYTE)
1611+ {
1612+ /* In order to adapt macro GELF_R_SYM and GELF_R_TYPE on mips64, need to convert
1613+ relocation info(raw data). Some eu-utils use read-mmap method to map file, so
1614+ we need to malloc and memcpy raw data to avoid segment fault. After modification,
1615+ the correct value are saved in the malloced memory not in process address space. */
1616+ scn->data_base = malloc (size);
1617+ if (scn->data_base == NULL)
1618+ {
1619+ __libelf_seterrno (ELF_E_NOMEM);
1620+ return;
1621+ }
1622+
1623+ /* The copy will be appropriately aligned for direct access. */
1624+ memcpy (scn->data_base, scn->rawdata_base, size);
1625+ }
1626+ else
1627+ {
1628+ xfct_t fp;
1629+
1630+ scn->data_base = malloc (size);
1631+ if (scn->data_base == NULL)
1632+ {
1633+ __libelf_seterrno (ELF_E_NOMEM);
1634+ return;
1635+ }
1636+
1637+ /* Make sure the source is correctly aligned for the conversion
1638+ function to directly access the data elements. */
1639+ char *rawdata_source;
1640+ /* In order to adapt macro GELF_R_SYM and GELF_R_TYPE on mips64, need to convert
1641+ relocation info(raw data). Some eu-utils use read-mmap method to map file, so
1642+ we need to malloc and memcpy raw data to avoid segment fault. After modification,
1643+ the correct value are saved in the malloced memory not in process address space. */
1644+ rawdata_source = malloc (size);
1645+ if (rawdata_source == NULL)
1646+ {
1647+ __libelf_seterrno (ELF_E_NOMEM);
1648+ return;
1649+ }
1650+
1651+ /* The copy will be appropriately aligned for direct access. */
1652+ memcpy (rawdata_source, scn->rawdata_base, size);
1653+
1654+ /* Get the conversion function. */
1655+ fp = __elf_xfctstom[eclass - 1][type];
1656+
1657+ fp (scn->data_base, rawdata_source, size, 0);
1658+
1659+ if (rawdata_source != scn->rawdata_base)
1660+ free (rawdata_source);
1661+ }
1662+
1663+ scn->data_list.data.d.d_buf = scn->data_base;
1664+ scn->data_list.data.d.d_size = size;
1665+ scn->data_list.data.d.d_type = type;
1666+ scn->data_list.data.d.d_off = scn->rawdata.d.d_off;
1667+ scn->data_list.data.d.d_align = scn->rawdata.d.d_align;
1668+ scn->data_list.data.d.d_version = scn->rawdata.d.d_version;
1669+
1670+ scn->data_list.data.s = scn;
1671+
1672+ /* In mips64 little-endian, r_info consists of four byte fields(contains
1673+ three reloc types) and a 32-bit symbol index. In order to adapt
1674+ GELF_R_SYM and GELF_R_TYPE, need to convert r_info to get correct symbol
1675+ index and type. */
1676+ /* references:
1677+ https://www.linux-mips.org/pub/linux/mips/doc/ABI/elf64-2.4.pdf
1678+ Page40 && Page41 */
1679+ GElf_Shdr shdr_mem;
1680+ GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
1681+ if (shdr->sh_type == SHT_REL)
1682+ {
1683+ size_t sh_entsize = gelf_fsize (scn->elf, ELF_T_REL, 1, EV_CURRENT);
1684+ int nentries = shdr->sh_size / sh_entsize;
1685+ for (int cnt = 0; cnt < nentries; ++cnt)
1686+ {
1687+ Elf_Data_Scn *data_scn = (Elf_Data_Scn *) &scn->data_list.data.d;
1688+ Elf64_Rel *value = &((Elf64_Rel *) data_scn->d.d_buf)[cnt];
1689+ Elf64_Xword info = value->r_info;
1690+ value->r_info = (((info & 0xffffffff) << 32)
1691+ | ((info >> 56) & 0xff)
1692+ | ((info >> 40) & 0xff00)
1693+ | ((info >> 24) & 0xff0000)
1694+ | ((info >> 8) & 0xff000000));
1695+ ((Elf64_Rel *) data_scn->d.d_buf)[cnt] = *value;
1696+ }
1697+ }
1698+ else if (shdr->sh_type == SHT_RELA)
1699+ {
1700+ size_t sh_entsize = gelf_fsize (scn->elf, ELF_T_RELA, 1, EV_CURRENT);
1701+ int nentries = shdr->sh_size / sh_entsize;
1702+ for (int cnt = 0; cnt < nentries; cnt++)
1703+ {
1704+ Elf_Data_Scn *data_scn = (Elf_Data_Scn *) &scn->data_list.data.d;
1705+ Elf64_Rela *value = &((Elf64_Rela *) data_scn->d.d_buf)[cnt];
1706+ Elf64_Xword info = value->r_info;
1707+ value->r_info = (((info & 0xffffffff) << 32)
1708+ | ((info >> 56) & 0xff)
1709+ | ((info >> 40) & 0xff00)
1710+ | ((info >> 24) & 0xff0000)
1711+ | ((info >> 8) & 0xff000000));
1712+ ((Elf64_Rela *) data_scn->d.d_buf)[cnt] = *value;
1713+ }
1714+ }
1715+}
1716+
1717+/* Convert the data in the current section. */
1718+static void
1719 convert_data (Elf_Scn *scn, int eclass,
1720 int data, size_t size, Elf_Type type)
1721 {
1722@@ -451,8 +564,23 @@ __libelf_set_data_list_rdlock (Elf_Scn *
1723 return;
1724 }
1725
1726- /* Convert according to the version and the type. */
1727- convert_data (scn, elf->class,
1728+ GElf_Shdr shdr_mem;
1729+ GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
1730+ GElf_Ehdr ehdr_mem;
1731+ GElf_Ehdr *ehdr = gelf_getehdr (scn->elf, &ehdr_mem);
1732+ if (shdr != NULL && (shdr->sh_type == SHT_RELA || shdr->sh_type == SHT_REL) &&
1733+ scn->elf->class == ELFCLASS64 && ehdr != NULL &&
1734+ ehdr->e_machine == EM_MIPS && ehdr->e_ident[EI_DATA] == ELFDATA2LSB)
1735+ convert_data_for_mips64el (scn, elf->class,
1736+ (elf->class == ELFCLASS32
1737+ || (offsetof (struct Elf, state.elf32.ehdr)
1738+ == offsetof (struct Elf, state.elf64.ehdr))
1739+ ? elf->state.elf32.ehdr->e_ident[EI_DATA]
1740+ : elf->state.elf64.ehdr->e_ident[EI_DATA]),
1741+ scn->rawdata.d.d_size, scn->rawdata.d.d_type);
1742+ else
1743+ /* Convert according to the version and the type. */
1744+ convert_data (scn, elf->class,
1745 (elf->class == ELFCLASS32
1746 || (offsetof (struct Elf, state.elf32.ehdr)
1747 == offsetof (struct Elf, state.elf64.ehdr))
1748--- a/libelf/elf_update.c
1749+++ b/libelf/elf_update.c
1750@@ -228,7 +228,60 @@ elf_update (Elf *elf, Elf_Cmd cmd)
1751 size = -1;
1752 }
1753 else
1754+ {
1755+ /* Because we converted the relocation info in mips order when we call elf_getdata.c,
1756+ so we need to convert the modified data in original order bits before writing the
1757+ data to the file. */
1758+ Elf_Scn *scn = NULL;
1759+ while ((scn = elf_nextscn (elf, scn)) != NULL)
1760+ {
1761+ GElf_Shdr shdr_mem;
1762+ GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
1763+ GElf_Ehdr ehdr_mem;
1764+ GElf_Ehdr *ehdr = gelf_getehdr (scn->elf, &ehdr_mem);
1765+ if (shdr != NULL && (shdr->sh_type == SHT_RELA || shdr->sh_type == SHT_REL) &&
1766+ scn->elf->class == ELFCLASS64 &&
1767+ ehdr != NULL && ehdr->e_machine == EM_MIPS && ehdr->e_ident[EI_DATA] == ELFDATA2LSB)
1768+ {
1769+ Elf_Data *d = elf_getdata (scn, NULL);
1770+ if (shdr->sh_type == SHT_REL)
1771+ {
1772+ size_t sh_entsize = gelf_fsize (scn->elf, ELF_T_REL, 1, EV_CURRENT);
1773+ int nentries = shdr->sh_size / sh_entsize;
1774+ for (int cnt = 0; cnt < nentries; ++cnt)
1775+ {
1776+ Elf_Data_Scn *data_scn = (Elf_Data_Scn *) d;
1777+ Elf64_Rel *value = &((Elf64_Rel *) data_scn->d.d_buf)[cnt];
1778+ Elf64_Xword info = value->r_info;
1779+ value->r_info = (info >> 32
1780+ | ((info << 56) & 0xff00000000000000)
1781+ | ((info << 40) & 0xff000000000000)
1782+ | ((info << 24) & 0xff0000000000)
1783+ | ((info << 8) & 0xff00000000));
1784+ ((Elf64_Rel *) data_scn->d.d_buf)[cnt] = *value;
1785+ }
1786+ }
1787+ else if (shdr->sh_type == SHT_RELA)
1788+ {
1789+ size_t sh_entsize = gelf_fsize (scn->elf, ELF_T_RELA, 1, EV_CURRENT);
1790+ int nentries = shdr->sh_size / sh_entsize;
1791+ for (int cnt = 0; cnt < nentries; cnt++)
1792+ {
1793+ Elf_Data_Scn *data_scn = (Elf_Data_Scn *) d;
1794+ Elf64_Rela *value = &((Elf64_Rela *) data_scn->d.d_buf)[cnt];
1795+ Elf64_Xword info = value->r_info;
1796+ value->r_info = (info >> 32
1797+ | ((info << 56) & 0xff00000000000000)
1798+ | ((info << 40) & 0xff000000000000)
1799+ | ((info << 24) & 0xff0000000000)
1800+ | ((info << 8) & 0xff00000000));
1801+ ((Elf64_Rela *) data_scn->d.d_buf)[cnt] = *value;
1802+ }
1803+ }
1804+ }
1805+ }
1806 size = write_file (elf, size, change_bo, shnum);
1807+ }
1808 }
1809
1810 out:
1811--- /dev/null
1812+++ b/backends/mips_attrs.c
1813@@ -0,0 +1,140 @@
1814+/* Object attribute tags for MIPS.
1815+ Copyright (C) 2024 CIP United Inc.
1816+ This file is part of elfutils.
1817+
1818+ This file is free software; you can redistribute it and/or modify
1819+ it under the terms of either
1820+
1821+ * the GNU Lesser General Public License as published by the Free
1822+ Software Foundation; either version 3 of the License, or (at
1823+ your option) any later version
1824+
1825+ or
1826+
1827+ * the GNU General Public License as published by the Free
1828+ Software Foundation; either version 2 of the License, or (at
1829+ your option) any later version
1830+
1831+ or both in parallel, as here.
1832+
1833+ elfutils is distributed in the hope that it will be useful, but
1834+ WITHOUT ANY WARRANTY; without even the implied warranty of
1835+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1836+ General Public License for more details.
1837+
1838+ You should have received copies of the GNU General Public License and
1839+ the GNU Lesser General Public License along with this program. If
1840+ not, see <http://www.gnu.org/licenses/>. */
1841+
1842+#ifdef HAVE_CONFIG_H
1843+# include <config.h>
1844+#endif
1845+
1846+#include <string.h>
1847+#include <dwarf.h>
1848+
1849+#define BACKEND mips_
1850+#include "libebl_CPU.h"
1851+
1852+#define KNOWN_VALUES(...) do \
1853+ { \
1854+ static const char *table[] = { __VA_ARGS__ }; \
1855+ if (value < sizeof table / sizeof table[0]) \
1856+ *value_name = table[value]; \
1857+ } while (0)
1858+
1859+//copy gnu attr tags from binutils-2.34/elfcpp/mips.h
1860+/* Object attribute tags. */
1861+enum
1862+{
1863+ /* 0-3 are generic. */
1864+
1865+ /* Floating-point ABI used by this object file. */
1866+ Tag_GNU_MIPS_ABI_FP = 4,
1867+
1868+ /* MSA ABI used by this object file. */
1869+ Tag_GNU_MIPS_ABI_MSA = 8,
1870+};
1871+
1872+/* Object attribute values. */
1873+enum
1874+{
1875+ /* Values defined for Tag_GNU_MIPS_ABI_MSA. */
1876+
1877+ /* Not tagged or not using any ABIs affected by the differences. */
1878+ Val_GNU_MIPS_ABI_MSA_ANY = 0,
1879+
1880+ /* Using 128-bit MSA. */
1881+ Val_GNU_MIPS_ABI_MSA_128 = 1,
1882+};
1883+
1884+/* Object attribute values. */
1885+enum
1886+{
1887+ /* This is reserved for backward-compatibility with an earlier
1888+ implementation of the MIPS NaN2008 functionality. */
1889+ Val_GNU_MIPS_ABI_FP_NAN2008 = 8,
1890+};
1891+
1892+/* copy binutils-2.34/binutils/readelf.c display_mips_gnu_attribute */
1893+bool
1894+mips_check_object_attribute (Ebl *ebl __attribute__ ((unused)),
1895+ const char *vendor, int tag, uint64_t value,
1896+ const char **tag_name, const char **value_name)
1897+{
1898+ if (!strcmp (vendor, "gnu"))
1899+ switch (tag)
1900+ {
1901+ case Tag_GNU_MIPS_ABI_FP:
1902+ *tag_name = "Tag_GNU_MIPS_ABI_FP";
1903+ switch (value)
1904+ {
1905+ case Val_GNU_MIPS_ABI_FP_ANY:
1906+ *value_name = "Hard or soft float";
1907+ return true;
1908+ case Val_GNU_MIPS_ABI_FP_DOUBLE:
1909+ *value_name = "Hard float (double precision)";
1910+ return true;
1911+ case Val_GNU_MIPS_ABI_FP_SINGLE:
1912+ *value_name = "Hard float (single precision)";
1913+ return true;
1914+ case Val_GNU_MIPS_ABI_FP_SOFT:
1915+ *value_name = "Soft float";
1916+ return true;
1917+ case Val_GNU_MIPS_ABI_FP_OLD_64:
1918+ *value_name = "Hard float (MIPS32r2 64-bit FPU 12 callee-saved)";
1919+ return true;
1920+ case Val_GNU_MIPS_ABI_FP_XX:
1921+ *value_name = "Hard float (32-bit CPU, Any FPU)";
1922+ return true;
1923+ case Val_GNU_MIPS_ABI_FP_64:
1924+ *value_name = "Hard float (32-bit CPU, 64-bit FPU)";
1925+ return true;
1926+ case Val_GNU_MIPS_ABI_FP_64A:
1927+ *value_name = "Hard float compat (32-bit CPU, 64-bit FPU)";
1928+ return true;
1929+ case Val_GNU_MIPS_ABI_FP_NAN2008:
1930+ *value_name = "NaN 2008 compatibility";
1931+ return true;
1932+ default:
1933+ return true;
1934+ }
1935+ return true;
1936+ case Tag_GNU_MIPS_ABI_MSA:
1937+ *tag_name = "Tag_GNU_MIPS_ABI_MSA";
1938+ switch (value)
1939+ {
1940+ case Val_GNU_MIPS_ABI_MSA_ANY:
1941+ *value_name = "Any MSA or not";
1942+ return true;
1943+ case Val_GNU_MIPS_ABI_MSA_128:
1944+ *value_name = "128-bit MSA";
1945+ return true;
1946+ default:
1947+ return true;
1948+ }
1949+ return true;
1950+ }
1951+
1952+ return false;
1953+}
1954--- a/src/readelf.c
1955+++ b/src/readelf.c
1956@@ -2219,17 +2219,41 @@ handle_relocs_rel (Ebl *ebl, GElf_Ehdr *
1957 (long int) GELF_R_SYM (rel->r_info));
1958 }
1959 else if (GELF_ST_TYPE (sym->st_info) != STT_SECTION)
1960- printf (" %#0*" PRIx64 " %-20s %#0*" PRIx64 " %s\n",
1961- class == ELFCLASS32 ? 10 : 18, rel->r_offset,
1962- likely (ebl_reloc_type_check (ebl,
1963- GELF_R_TYPE (rel->r_info)))
1964- /* Avoid the leading R_ which isn't carrying any
1965- information. */
1966- ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
1967- buf, sizeof (buf)) + 2
1968- : _("<INVALID RELOC>"),
1969- class == ELFCLASS32 ? 10 : 18, sym->st_value,
1970- elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name));
1971+ {
1972+ unsigned long inf = rel->r_info;
1973+ printf (" %#0*" PRIx64 " %-20s %#0*" PRIx64 " %s\n",
1974+ class == ELFCLASS32 ? 10 : 18, rel->r_offset,
1975+ likely (ebl_reloc_type_check (ebl,
1976+ GELF_R_TYPE (rel->r_info)))
1977+ /* Avoid the leading R_ which isn't carrying any
1978+ information. */
1979+ ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
1980+ buf, sizeof (buf)) + 2
1981+ : _("<INVALID RELOC>"),
1982+ class == ELFCLASS32 ? 10 : 18, sym->st_value,
1983+ elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name));
1984+
1985+ /* copy binutils-2.34/binutils/readelf.c dump_relocations+1753 */
1986+ if(ebl->elf->class == ELFCLASS64 && ebl->elf->state.elf64.ehdr->e_machine == EM_MIPS)
1987+ {
1988+ unsigned int type2 = ELF64_MIPS_R_TYPE2 (inf);
1989+ unsigned int type3 = ELF64_MIPS_R_TYPE3 (inf);
1990+ const char * rtype2 = ebl_reloc_type_name (ebl, type2, buf, sizeof (buf)) + 2;
1991+ const char * rtype3 = ebl_reloc_type_name (ebl, type3, buf, sizeof (buf)) + 2;
1992+ printf(" Type2: ");
1993+ if (rtype2 == NULL)
1994+ printf (_("unrecognized: %lx"), (unsigned long) type2 & 0xffffffff);
1995+ else
1996+ printf ("%s", rtype2);
1997+
1998+ printf ("\n Type3: ");
1999+ if (rtype3 == NULL)
2000+ printf (_("unrecognized: %lx"), (unsigned long) type3 & 0xffffffff);
2001+ else
2002+ printf ("%s", rtype3);
2003+ printf("\n");
2004+ }
2005+ }
2006 else
2007 {
2008 /* This is a relocation against a STT_SECTION symbol. */
2009@@ -2253,16 +2277,40 @@ handle_relocs_rel (Ebl *ebl, GElf_Ehdr *
2010 (long int) (sym->st_shndx == SHN_XINDEX
2011 ? xndx : sym->st_shndx));
2012 else
2013- printf (" %#0*" PRIx64 " %-20s %#0*" PRIx64 " %s\n",
2014- class == ELFCLASS32 ? 10 : 18, rel->r_offset,
2015- ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
2016- /* Avoid the leading R_ which isn't carrying any
2017- information. */
2018- ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
2019- buf, sizeof (buf)) + 2
2020- : _("<INVALID RELOC>"),
2021- class == ELFCLASS32 ? 10 : 18, sym->st_value,
2022- elf_strptr (ebl->elf, shstrndx, secshdr->sh_name));
2023+ {
2024+ unsigned long inf = rel->r_info;
2025+ printf (" %#0*" PRIx64 " %-20s %#0*" PRIx64 " %s\n",
2026+ class == ELFCLASS32 ? 10 : 18, rel->r_offset,
2027+ ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
2028+ /* Avoid the leading R_ which isn't carrying any
2029+ information. */
2030+ ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
2031+ buf, sizeof (buf)) + 2
2032+ : _("<INVALID RELOC>"),
2033+ class == ELFCLASS32 ? 10 : 18, sym->st_value,
2034+ elf_strptr (ebl->elf, shstrndx, secshdr->sh_name));
2035+
2036+ /* copy binutils-2.34/binutils/readelf.c dump_relocations+1753 */
2037+ if(ebl->elf->class == ELFCLASS64 && ebl->elf->state.elf64.ehdr->e_machine == EM_MIPS)
2038+ {
2039+ unsigned int type2 = ELF64_MIPS_R_TYPE2 (inf);
2040+ unsigned int type3 = ELF64_MIPS_R_TYPE3 (inf);
2041+ const char * rtype2 = ebl_reloc_type_name (ebl, type2, buf, sizeof (buf)) + 2;
2042+ const char * rtype3 = ebl_reloc_type_name (ebl, type3, buf, sizeof (buf)) + 2;
2043+ printf(" Type2: ");
2044+ if (rtype2 == NULL)
2045+ printf (_("unrecognized: %lx"), (unsigned long) type2 & 0xffffffff);
2046+ else
2047+ printf ("%s", rtype2);
2048+
2049+ printf ("\n Type3: ");
2050+ if (rtype3 == NULL)
2051+ printf (_("unrecognized: %lx"), (unsigned long) type3 & 0xffffffff);
2052+ else
2053+ printf ("%s", rtype3);
2054+ printf("\n");
2055+ }
2056+ }
2057 }
2058 }
2059 }
2060@@ -2410,19 +2458,43 @@ handle_relocs_rela (Ebl *ebl, GElf_Ehdr
2061 (long int) GELF_R_SYM (rel->r_info));
2062 }
2063 else if (GELF_ST_TYPE (sym->st_info) != STT_SECTION)
2064- printf ("\
2065+ {
2066+ unsigned long inf = rel->r_info;
2067+ printf ("\
2068 %#0*" PRIx64 " %-15s %#0*" PRIx64 " %+6" PRId64 " %s\n",
2069- class == ELFCLASS32 ? 10 : 18, rel->r_offset,
2070- likely (ebl_reloc_type_check (ebl,
2071- GELF_R_TYPE (rel->r_info)))
2072- /* Avoid the leading R_ which isn't carrying any
2073- information. */
2074- ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
2075- buf, sizeof (buf)) + 2
2076- : _("<INVALID RELOC>"),
2077- class == ELFCLASS32 ? 10 : 18, sym->st_value,
2078- rel->r_addend,
2079- elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name));
2080+ class == ELFCLASS32 ? 10 : 18, rel->r_offset,
2081+ likely (ebl_reloc_type_check (ebl,
2082+ GELF_R_TYPE (rel->r_info)))
2083+ /* Avoid the leading R_ which isn't carrying any
2084+ information. */
2085+ ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
2086+ buf, sizeof (buf)) + 2
2087+ : _("<INVALID RELOC>"),
2088+ class == ELFCLASS32 ? 10 : 18, sym->st_value,
2089+ rel->r_addend,
2090+ elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name));
2091+
2092+ /* copy binutils-2.34/binutils/readelf.c dump_relocations+1753 */
2093+ if(ebl->elf->class == ELFCLASS64 && ebl->elf->state.elf64.ehdr->e_machine == EM_MIPS)
2094+ {
2095+ unsigned int type2 = ELF64_MIPS_R_TYPE2 (inf);
2096+ unsigned int type3 = ELF64_MIPS_R_TYPE3 (inf);
2097+ const char * rtype2 = ebl_reloc_type_name (ebl, type2, buf, sizeof (buf)) + 2;
2098+ const char * rtype3 = ebl_reloc_type_name (ebl, type3, buf, sizeof (buf)) + 2;
2099+ printf(" Type2: ");
2100+ if (rtype2 == NULL)
2101+ printf (_("unrecognized: %lx"), (unsigned long) type2 & 0xffffffff);
2102+ else
2103+ printf ("%s", rtype2);
2104+
2105+ printf ("\n Type3: ");
2106+ if (rtype3 == NULL)
2107+ printf (_("unrecognized: %lx"), (unsigned long) type3 & 0xffffffff);
2108+ else
2109+ printf ("%s", rtype3);
2110+ printf("\n");
2111+ }
2112+ }
2113 else
2114 {
2115 /* This is a relocation against a STT_SECTION symbol. */
2116@@ -2446,18 +2518,42 @@ handle_relocs_rela (Ebl *ebl, GElf_Ehdr
2117 (long int) (sym->st_shndx == SHN_XINDEX
2118 ? xndx : sym->st_shndx));
2119 else
2120- printf ("\
2121+ {
2122+ unsigned long inf = rel->r_info;
2123+ printf ("\
2124 %#0*" PRIx64 " %-15s %#0*" PRIx64 " %+6" PRId64 " %s\n",
2125- class == ELFCLASS32 ? 10 : 18, rel->r_offset,
2126- ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
2127- /* Avoid the leading R_ which isn't carrying any
2128- information. */
2129- ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
2130- buf, sizeof (buf)) + 2
2131- : _("<INVALID RELOC>"),
2132- class == ELFCLASS32 ? 10 : 18, sym->st_value,
2133- rel->r_addend,
2134- elf_strptr (ebl->elf, shstrndx, secshdr->sh_name));
2135+ class == ELFCLASS32 ? 10 : 18, rel->r_offset,
2136+ ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
2137+ /* Avoid the leading R_ which isn't carrying any
2138+ information. */
2139+ ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
2140+ buf, sizeof (buf)) + 2
2141+ : _("<INVALID RELOC>"),
2142+ class == ELFCLASS32 ? 10 : 18, sym->st_value,
2143+ rel->r_addend,
2144+ elf_strptr (ebl->elf, shstrndx, secshdr->sh_name));
2145+
2146+ /* copy binutils-2.34/binutils/readelf.c dump_relocations+1753 */
2147+ if(ebl->elf->class == ELFCLASS64 && ebl->elf->state.elf64.ehdr->e_machine == EM_MIPS)
2148+ {
2149+ unsigned int type2 = ELF64_MIPS_R_TYPE2 (inf);
2150+ unsigned int type3 = ELF64_MIPS_R_TYPE3 (inf);
2151+ const char * rtype2 = ebl_reloc_type_name (ebl, type2, buf, sizeof (buf)) + 2;
2152+ const char * rtype3 = ebl_reloc_type_name (ebl, type3, buf, sizeof (buf)) + 2;
2153+ printf(" Type2: ");
2154+ if (rtype2 == NULL)
2155+ printf (_("unrecognized: %-7lx"), (unsigned long) type2 & 0xffffffff);
2156+ else
2157+ printf ("%s", rtype2);
2158+
2159+ printf ("\n Type3: ");
2160+ if (rtype3 == NULL)
2161+ printf (_("unrecognized: %lx"), (unsigned long) type3 & 0xffffffff);
2162+ else
2163+ printf ("%s", rtype3);
2164+ printf("\n");
2165+ }
2166+ }
2167 }
2168 }
2169 }
2170@@ -12043,7 +12139,7 @@ print_debug (Dwfl_Module *dwflmod, Ebl *
2171 GElf_Shdr shdr_mem;
2172 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
2173
2174- if (shdr != NULL && shdr->sh_type == SHT_PROGBITS)
2175+ if (shdr != NULL && is_debug_section_type(shdr->sh_type))
2176 {
2177 const char *name = elf_strptr (ebl->elf, shstrndx,
2178 shdr->sh_name);
2179@@ -12073,7 +12169,7 @@ print_debug (Dwfl_Module *dwflmod, Ebl *
2180 GElf_Shdr shdr_mem;
2181 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
2182
2183- if (shdr != NULL && shdr->sh_type == SHT_PROGBITS)
2184+ if (shdr != NULL && is_debug_section_type(shdr->sh_type))
2185 {
2186 static const struct
2187 {
2188--- a/tests/Makefile.am
2189+++ b/tests/Makefile.am
2190@@ -214,7 +214,7 @@ TESTS = run-arextract.sh run-arsymtest.s
2191 run-nvidia-extended-linemap-libdw.sh run-nvidia-extended-linemap-readelf.sh \
2192 run-readelf-dw-form-indirect.sh run-strip-largealign.sh \
2193 run-readelf-Dd.sh run-dwfl-core-noncontig.sh run-cu-dwp-section-info.sh \
2194- run-declfiles.sh
2195+ run-declfiles.sh run-readelf-reloc.sh
2196
2197 if !BIARCH
2198 export ELFUTILS_DISABLE_BIARCH = 1
2199@@ -646,7 +646,8 @@ EXTRA_DIST = run-arextract.sh run-arsymt
2200 testfile-dwp-5-cu-index-overflow.dwp.bz2 \
2201 testfile-dwp-4-cu-index-overflow.bz2 \
2202 testfile-dwp-4-cu-index-overflow.dwp.bz2 \
2203- testfile-dwp-cu-index-overflow.source
2204+ testfile-dwp-cu-index-overflow.source \
2205+ run-readelf-reloc.sh
2206
2207
2208 if USE_VALGRIND
2209--- /dev/null
2210+++ b/tests/run-readelf-reloc.sh
2211@@ -0,0 +1,42 @@
2212+#! /bin/bash
2213+# Copyright (C) 2024 CIP United Inc.
2214+# This file is part of elfutils.
2215+#
2216+# This file is free software; you can redistribute it and/or modify
2217+# it under the terms of the GNU General Public License as published by
2218+# the Free Software Foundation; either version 3 of the License, or
2219+# (at your option) any later version.
2220+#
2221+# elfutils is distributed in the hope that it will be useful, but
2222+# WITHOUT ANY WARRANTY; without even the implied warranty of
2223+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2224+# GNU General Public License for more details.
2225+#
2226+# You should have received a copy of the GNU General Public License
2227+# along with this program. If not, see <http://www.gnu.org/licenses/>.
2228+
2229+. $srcdir/test-subr.sh
2230+
2231+tempfiles test-readelf-h.txt test-readelf-reloc.txt
2232+testrun ${abs_top_builddir}/src/readelf -h ${abs_top_builddir}/src/strip.o > test-readelf-h.txt
2233+machine=`cat test-readelf-h.txt | grep Machine`
2234+class=`cat test-readelf-h.txt | grep Class`
2235+endian=`cat test-readelf-h.txt | grep Data`
2236+if [[ "$machine" == *MIPS* && "$class" == *ELF64 && "$endian" == *little* ]]; then
2237+testrun ${abs_top_builddir}/src/readelf -r ${abs_top_builddir}/src/strip.o | head -n 12 | tail -n 10 > test-readelf-reloc.txt
2238+
2239+testrun_compare cat test-readelf-reloc.txt << EOF
2240+ Offset Type Value Addend Name
2241+ 0x0000000000000008 MIPS_GPREL16 000000000000000000 +0 .text
2242+ Type2: MIPS_SUB
2243+ Type3: MIPS_HI16
2244+ 0x0000000000000010 MIPS_GPREL16 000000000000000000 +0 .text
2245+ Type2: MIPS_SUB
2246+ Type3: MIPS_LO16
2247+ 0x0000000000000014 MIPS_CALL16 000000000000000000 +0 gelf_getehdr
2248+ Type2: MIPS_NONE
2249+ Type3: MIPS_NONE
2250+EOF
2251+fi
2252+
2253+exit 0
2254--- a/src/elflint.c
2255+++ b/src/elflint.c
2256@@ -936,7 +936,9 @@ section [%2d] '%s': symbol %zu (%s): non
2257 }
2258
2259 if (GELF_ST_TYPE (sym->st_info) == STT_SECTION
2260- && GELF_ST_BIND (sym->st_info) != STB_LOCAL)
2261+ && GELF_ST_BIND (sym->st_info) != STB_LOCAL
2262+ && ehdr->e_machine != EM_MIPS
2263+ && strcmp (name, "_DYNAMIC_LINKING") != 0)
2264 ERROR (_("\
2265 section [%2d] '%s': symbol %zu (%s): non-local section symbol\n"),
2266 idx, section_name (ebl, idx), cnt, name);
2267@@ -3828,6 +3830,10 @@ cannot get section header for section [%
2268 && ebl_bss_plt_p (ebl))
2269 good_type = SHT_NOBITS;
2270
2271+ if (ehdr->e_machine == EM_MIPS
2272+ && (strstr(special_sections[s].name, ".debug") != NULL))
2273+ good_type = SHT_MIPS_DWARF;
2274+
2275 /* In a debuginfo file, any normal section can be SHT_NOBITS.
2276 This is only invalid for DWARF sections and .shstrtab. */
2277 if (shdr->sh_type != good_type
2278@@ -3988,12 +3994,21 @@ section [%2zu] '%s': size not multiple o
2279 ERROR (_("section [%2zu] '%s'"
2280 " contains invalid processor-specific flag(s)"
2281 " %#" PRIx64 "\n"),
2282- cnt, section_name (ebl, cnt), sh_flags & SHF_MASKPROC);
2283+ cnt, section_name (ebl, cnt), sh_flags & SHF_MASKPROC);
2284 sh_flags &= ~(GElf_Xword) SHF_MASKPROC;
2285 }
2286 if (sh_flags & SHF_MASKOS)
2287- if (gnuld)
2288- sh_flags &= ~(GElf_Xword) SHF_GNU_RETAIN;
2289+ {
2290+ if (gnuld)
2291+ sh_flags &= ~(GElf_Xword) SHF_GNU_RETAIN;
2292+ if (!ebl_machine_section_flag_check (ebl,
2293+ sh_flags & SHF_MASKOS))
2294+ ERROR (_("section [%2zu] '%s'"
2295+ " contains invalid os-specific flag(s)"
2296+ " %#" PRIx64 "\n"),
2297+ cnt, section_name (ebl, cnt), sh_flags & SHF_MASKOS);
2298+ sh_flags &= ~(GElf_Xword) SHF_MASKOS;
2299+ }
2300 if (sh_flags != 0)
2301 ERROR (_("section [%2zu] '%s' contains unknown flag(s)"
2302 " %#" PRIx64 "\n"),
2303@@ -4059,6 +4074,7 @@ section [%2zu] '%s': merge flag set but
2304 switch (shdr->sh_type)
2305 {
2306 case SHT_PROGBITS:
2307+ case SHT_MIPS_DWARF:
2308 break;
2309
2310 case SHT_NOBITS:
2311@@ -4716,7 +4732,7 @@ program header offset in ELF header and
2312 if (shdr != NULL
2313 && ((is_debuginfo && shdr->sh_type == SHT_NOBITS)
2314 || (! is_debuginfo
2315- && (shdr->sh_type == SHT_PROGBITS
2316+ && (is_debug_section_type(shdr->sh_type)
2317 || shdr->sh_type == SHT_X86_64_UNWIND)))
2318 && elf_strptr (ebl->elf, shstrndx, shdr->sh_name) != NULL
2319 && ! strcmp (".eh_frame_hdr",
2320--- /dev/null
2321+++ b/backends/mips64_corenote.c
2322@@ -0,0 +1,2 @@
2323+#define BITS 64
2324+#include "mips_corenote.c"
2325--- a/libebl/eblcorenotetypename.c
2326+++ b/libebl/eblcorenotetypename.c
2327@@ -94,6 +94,8 @@ ebl_core_note_type_name (Ebl *ebl, uint3
2328 KNOWNSTYPE (ARM_SYSTEM_CALL);
2329 KNOWNSTYPE (SIGINFO);
2330 KNOWNSTYPE (FILE);
2331+ KNOWNSTYPE (MIPS_FP_MODE);
2332+ KNOWNSTYPE (MIPS_MSA);
2333 #undef KNOWNSTYPE
2334
2335 default:
2336--- a/tests/run-allregs.sh
2337+++ b/tests/run-allregs.sh
2338@@ -2904,4 +2904,83 @@ FPU registers:
2339 62: ft10 (ft10), float 64 bits
2340 63: ft11 (ft11), float 64 bits
2341 EOF
2342+
2343+# See run-readelf-mixed-corenote.sh for instructions to regenerate
2344+# this core file.
2345+regs_test testfile-mips64-core <<\EOF
2346+integer registers:
2347+ 0: $0 (0), signed 32 bits
2348+ 1: $1 (1), signed 32 bits
2349+ 2: $2 (2), signed 32 bits
2350+ 3: $3 (3), signed 32 bits
2351+ 4: $4 (4), signed 32 bits
2352+ 5: $5 (5), signed 32 bits
2353+ 6: $6 (6), signed 32 bits
2354+ 7: $7 (7), signed 32 bits
2355+ 8: $8 (8), signed 32 bits
2356+ 9: $9 (9), signed 32 bits
2357+ 10: $10 (10), signed 32 bits
2358+ 11: $11 (11), signed 32 bits
2359+ 12: $12 (12), signed 32 bits
2360+ 13: $13 (13), signed 32 bits
2361+ 14: $14 (14), signed 32 bits
2362+ 15: $15 (15), signed 32 bits
2363+ 16: $16 (16), signed 32 bits
2364+ 17: $17 (17), signed 32 bits
2365+ 18: $18 (18), signed 32 bits
2366+ 19: $19 (19), signed 32 bits
2367+ 20: $20 (20), signed 32 bits
2368+ 21: $21 (21), signed 32 bits
2369+ 22: $22 (22), signed 32 bits
2370+ 23: $23 (23), signed 32 bits
2371+ 24: $24 (24), signed 32 bits
2372+ 25: $25 (25), signed 32 bits
2373+ 26: $26 (26), signed 32 bits
2374+ 27: $27 (27), signed 32 bits
2375+ 28: $28 (28), address 32 bits
2376+ 29: $29 (29), address 32 bits
2377+ 30: $30 (30), signed 32 bits
2378+ 31: $31 (31), address 32 bits
2379+ 32: $lo (lo), signed 32 bits
2380+ 33: $hi (hi), signed 32 bits
2381+ 34: $pc (pc), signed 32 bits
2382+ 35: $bad (bad), address 32 bits
2383+ 36: $sr (sr), signed 32 bits
2384+ 37: $cause (cause), address 32 bits
2385+FPU registers:
2386+ 38: $f0 (f0), float 64 bits
2387+ 39: $f1 (f1), float 64 bits
2388+ 40: $f2 (f2), float 64 bits
2389+ 41: $f3 (f3), float 64 bits
2390+ 42: $f4 (f4), float 64 bits
2391+ 43: $f5 (f5), float 64 bits
2392+ 44: $f6 (f6), float 64 bits
2393+ 45: $f7 (f7), float 64 bits
2394+ 46: $f8 (f8), float 64 bits
2395+ 47: $f9 (f9), float 64 bits
2396+ 48: $f10 (f10), float 64 bits
2397+ 49: $f11 (f11), float 64 bits
2398+ 50: $f12 (f12), float 64 bits
2399+ 51: $f13 (f13), float 64 bits
2400+ 52: $f14 (f14), float 64 bits
2401+ 53: $f15 (f15), float 64 bits
2402+ 54: $f16 (f16), float 64 bits
2403+ 55: $f17 (f17), float 64 bits
2404+ 56: $f18 (f18), float 64 bits
2405+ 57: $f19 (f19), float 64 bits
2406+ 58: $f20 (f20), float 64 bits
2407+ 59: $f21 (f21), float 64 bits
2408+ 60: $f22 (f22), float 64 bits
2409+ 61: $f23 (f23), float 64 bits
2410+ 62: $f24 (f24), float 64 bits
2411+ 63: $f25 (f25), float 64 bits
2412+ 64: $f26 (f26), float 64 bits
2413+ 65: $f27 (f27), float 64 bits
2414+ 66: $f28 (f28), float 64 bits
2415+ 67: $f29 (f29), float 64 bits
2416+ 68: $f30 (f30), float 64 bits
2417+ 69: $f31 (f31), float 64 bits
2418+ 70: $fsr (fsr), float 64 bits
2419+ 71: $fir (fir), float 64 bits
2420+EOF
2421 exit 0
2422--- a/tests/run-readelf-mixed-corenote.sh
2423+++ b/tests/run-readelf-mixed-corenote.sh
2424@@ -716,4 +716,101 @@ Note segment of 1408 bytes at offset 0x3
2425 2000155000-2000157000 00122000 8192 /lib64/libc-2.27.so
2426 EOF
2427
2428+# To reproduce this core dump, do this on a mips machine:
2429+# $ gcc -x c <(echo 'int main () { return *(int *)0x12345678; }')
2430+# $ ./a.out
2431+testfiles testfile-mips64-core
2432+testrun_compare ${abs_top_builddir}/src/readelf -n testfile-mips64-core <<\EOF
2433+
2434+Note segment of 2572 bytes at offset 0x3c0:
2435+ Owner Data size Type
2436+ CORE 480 PRSTATUS
2437+ info.si_signo: 11, info.si_code: 0, info.si_errno: 0, cursig: 11
2438+ sigpend: <>
2439+ sighold: <>
2440+ pid: 1660204, ppid: 1457483, pgrp: 1660204, sid: 1457483
2441+ utime: 0.000000, stime: 0.012000, cutime: 0.000000, cstime: 0.000000
2442+ pc: 0x000000aaacce0a64, fpvalid: 1
2443+ bad: 0x12345678 sr: 0 cause: 0x0400ccf3
2444+ f0: 0x1000000800000000 f1: 0x0000000000000000 f2: 0x0000000000000000
2445+ f3: 0x0000000000000000 f4: 0x0000000000000000 f5: 0x0000000000000000
2446+ f6: 0x0000000000000000
2447+ 0: 0 1: 0 2: 1
2448+ 3: 0 4: 305419896 5: 0
2449+ 6: -73593800 7: 255 8: 1
2450+ 9: 0 10: -73593464 11: 255
2451+ 12: -73593448 13: 255 14: 0
2452+ 15: 0 16: -244869184 17: 255
2453+ 18: -244886336 19: 255 20: -73593472
2454+ 21: 255 22: -1 23: -1
2455+ 24: 3 25: 0 26: 3167716
2456+ 27: 0 28: 0x00000024 29: 0x00000000
2457+ 30: 49495 31: 0x00000000 lo: -73593464
2458+ hi: 255 bad: 0x12345678 sr: 0
2459+ cause: 0x0400ccf3 f0: 0x1000000800000000
2460+ f1: 0x0000000000000000 f2: 0x0000000000000000
2461+ f3: 0x0000000000000000 f4: 0x0000000000000000
2462+ f5: 0x0000000000000000 f6: 0x0000000000000000
2463+ CORE 136 PRPSINFO
2464+ state: 0, sname: R, zomb: 0, nice: 0, flag: 0x0000000000402600
2465+ uid: 1014, gid: 100, pid: 1660204, ppid: 1457483, pgrp: 1660204
2466+ sid: 1457483
2467+ fname: a.out, psargs: ./a.out
2468+ CORE 128 SIGINFO
2469+ si_signo: 11, si_errno: 1, si_code: 0
2470+ sender PID: 305419896, sender UID: 0
2471+ CORE 320 AUXV
2472+ SYSINFO_EHDR: 0xffff14c000
2473+ HWCAP: 0x7806
2474+ PAGESZ: 16384
2475+ CLKTCK: 100
2476+ PHDR: 0xaaacce0040
2477+ PHENT: 56
2478+ PHNUM: 9
2479+ BASE: 0xfff1694000
2480+ FLAGS: 0
2481+ ENTRY: 0xaaacce08d0
2482+ UID: 1014
2483+ EUID: 1014
2484+ GID: 100
2485+ EGID: 100
2486+ SECURE: 0
2487+ RANDOM: 0xfffb9d0f9c
2488+ EXECFN: 0xfffb9d3ff0
2489+ PLATFORM: 0xfffb9d0fb5
2490+ BASE_PLATFORM: 0xfffb9d0fac
2491+ NULL
2492+ CORE 549 FILE
2493+ 9 files:
2494+ aaacce0000-aaacce4000 00000000 16384 /tmp/a.out
2495+ aaaccf0000-aaaccf4000 00000000 16384 /tmp/a.out
2496+ fff1470000-fff165c000 00000000 2015232 /usr/lib/mips64el-linux-gnuabi64/libc.so.6
2497+ fff165c000-fff1668000 001ec000 49152 /usr/lib/mips64el-linux-gnuabi64/libc.so.6
2498+ fff1668000-fff1670000 001e8000 32768 /usr/lib/mips64el-linux-gnuabi64/libc.so.6
2499+ fff1670000-fff1678000 001f0000 32768 /usr/lib/mips64el-linux-gnuabi64/libc.so.6
2500+ fff1694000-fff16c4000 00000000 196608 /usr/lib/mips64el-linux-gnuabi64/ld.so.1
2501+ fff16d0000-fff16d4000 0002c000 16384 /usr/lib/mips64el-linux-gnuabi64/ld.so.1
2502+ fff16d4000-fff16d8000 00030000 16384 /usr/lib/mips64el-linux-gnuabi64/ld.so.1
2503+ CORE 264 FPREGSET
2504+ fcs: 0x000c0000, fir: 0x00f70501
2505+ f0: 0xffffffffffffffff f1: 0xffffffffffffffff
2506+ f2: 0xffffffffffffffff f3: 0xffffffffffffffff
2507+ f4: 0xffffffffffffffff f5: 0xffffffffffffffff
2508+ f6: 0xffffffffffffffff f7: 0xffffffffffffffff
2509+ f8: 0xffffffffffffffff f9: 0xffffffffffffffff
2510+ f10: 0xffffffffffffffff f11: 0xffffffffffffffff
2511+ f12: 0xffffffffffffffff f13: 0xffffffffffffffff
2512+ f14: 0xffffffffffffffff f15: 0xffffffffffffffff
2513+ f16: 0xffffffffffffffff f17: 0xffffffffffffffff
2514+ f18: 0xffffffffffffffff f19: 0xffffffffffffffff
2515+ f20: 0xffffffffffffffff f21: 0xffffffffffffffff
2516+ f22: 0xffffffffffffffff f23: 0xffffffffffffffff
2517+ f24: 0xffffffffffffffff f25: 0xffffffffffffffff
2518+ f26: 0xffffffffffffffff f27: 0xffffffffffffffff
2519+ f28: 0xffffffffffffffff f29: 0xffffffffffffffff
2520+ f30: 0xffffffffffffffff f31: 0xffffffffffffffff
2521+ LINUX 4 MIPS_FP_MODE
2522+ LINUX 528 MIPS_MSA
2523+EOF
2524+
2525 exit 0