[1/5] strip: Adapt src/strip -o -f on mips
Commit Message
From: Ying Huang <ying.huang@oss.cipunited.com>
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
Comments
Hi,
On Tue, 2023-04-11 at 16:12 +0800, Ying Huang wrote:
> From: Ying Huang <ying.huang@oss.cipunited.com>
>
> 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.
Is there a spec that describes this?
I see you adjusted elf.h to include:
+#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)
And various new relocation types for MIPS variants.
Our elf.h comes from the glibc project. Have you also submitted these
changes to libc-alpha@sourceware.org ?
> 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.
Where do these segfaults show up?
> 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.
It feels like this is in the wrong place and doesn't take into account
whether the program itself is running on a big or little endian
machine.
Maybe I am misunderstanding why this conversion is needed always. But I
would have expected a specific conversion function for MIPS for
ELF_T_REL and/or ELF_T_RELA (which are currently generic).
Cheers,
Mark
Hi,
在 2023/5/9 23:15, Mark Wielaard 写道:
> Hi,
>
> On Tue, 2023-04-11 at 16:12 +0800, Ying Huang wrote:
>> From: Ying Huang <ying.huang@oss.cipunited.com>
>>
>> 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.
> Is there a spec that describes this?
references:
https://www.linux-mips.org/pub/linux/mips/doc/ABI/elf64-2.4.pdf
Page40 && Page41
>
> I see you adjusted elf.h to include:
>
> +#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)
>
> And various new relocation types for MIPS variants.
> Our elf.h comes from the glibc project. Have you also submitted these
> changes to libc-alpha@sourceware.org ?
Has submitted.
https://sourceware.org/pipermail/libc-alpha/2023-May/148026.html
https://sourceware.org/pipermail/libc-alpha/2023-May/148112.html
>
>> 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.
> Where do these segfaults show up?
>
>> 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.
Has tested on big/little endian machine with big/little endian ELF file, all were OK.
> It feels like this is in the wrong place and doesn't take into account
> whether the program itself is running on a big or little endian
> machine.
>
> Maybe I am misunderstanding why this conversion is needed always. But I
> would have expected a specific conversion function for MIPS for
> ELF_T_REL and/or ELF_T_RELA (which are currently generic).
>
> Cheers,
>
> Mark
1.Considering that some people directly use the original data instead of the interface function gelf_getrela;
2.Because there is only one parameter, so can not modify the macro ELF64_R_TYPE;
3.If the mips interface function is added, other packages using libelf will not be compatible with mips, and the place where gelf_getrela is used need be modified.
Where do you think is the most suitable place to do mips conversion?
Thanks,
Ying
HI,
>> 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.
> Where do these segfaults show up?
The screenshot of the segment error was not uploaded successfully in the last email, upload again.
Thanks,
YIng
在 2023/5/16 14:46, Ying Huang 写道:
>
> HI,
>
> >> 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.
> > Where do these segfaults show up?
> The screenshot of the segment error was not uploaded successfully in the last email, upload again.
>
> Thanks,
>
> YIng
>
huangying@Sleepygon:~/elf/elfutils_4$ src/elflint src/nm.o
Segmentation fault
huangying@Sleepygon:~/elf/elfutils_4$ src/elflint src/strip.o
Segmentation fault
On 09/05/2023 16:15, Mark Wielaard wrote:
> Hi,
>
> On Tue, 2023-04-11 at 16:12 +0800, Ying Huang wrote:
>> From: Ying Huang <ying.huang@oss.cipunited.com>
>>
>> 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.
>
> Is there a spec that describes this?
>
> I see you adjusted elf.h to include:
>
> +#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)
>
Is this patch intended to support 32 bit MIPS (and MIPSEL) ?
For me it did not work but I could see if I can add that in.
(From a very long time ago, I have some patches based on the debian MIPS
support but I never managed to find time to upstream them, so this is
great to finally see!)
Luke
Hi Ying,
On Tue, May 16, 2023 at 02:38:45PM +0800, Ying Huang wrote:
> 在 2023/5/9 23:15, Mark Wielaard 写道:
> > On Tue, 2023-04-11 at 16:12 +0800, Ying Huang wrote:
> >> 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.
> > Is there a spec that describes this?
>
>
> references:
>
> https://www.linux-mips.org/pub/linux/mips/doc/ABI/elf64-2.4.pdf
>
> Page40 && Page41
Thanks. Interesting. If possible please include this URL in a comment.
> > I see you adjusted elf.h to include:
> >
> > +#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)
> >
> > And various new relocation types for MIPS variants.
> > Our elf.h comes from the glibc project. Have you also submitted these
> > changes to libc-alpha@sourceware.org ?
> Has submitted.
>
> https://sourceware.org/pipermail/libc-alpha/2023-May/148026.html
>
> https://sourceware.org/pipermail/libc-alpha/2023-May/148112.html
Thanks. We'll sync them as soon as v3 lands.
> Has tested on big/little endian machine with big/little endian
> ELF file, all were OK.
Could you post those ELF files somewhere?
Maybe we can add some as test files?
> > It feels like this is in the wrong place and doesn't take into account
> > whether the program itself is running on a big or little endian
> > machine.
> >
> > Maybe I am misunderstanding why this conversion is needed always. But I
> > would have expected a specific conversion function for MIPS for
> > ELF_T_REL and/or ELF_T_RELA (which are currently generic).
>
> 1.Considering that some people directly use the original data instead of the interface function gelf_getrela;
>
> 2.Because there is only one parameter, so can not modify the macro ELF64_R_TYPE;
>
> 3.If the mips interface function is added, other packages using libelf will not be compatible with mips, and the place where gelf_getrela is used need be modified.
>
> Where do you think is the most suitable place to do mips conversion?
So for the convert_data case in elf_getdata.c I would expect a special
conversion function being defined for ELF_T_REL and ELF_T_RELA. This
normally comes from __elf_xfctstom. I realize now that cannot easily
take an Elf of machine type. But I would expect to have the conversion
be done by a new function that can be assigned to fp in convert_data:
/* Get the conversion function. */
fp = __elf_xfctstom[eclass - 1][type];
I still don't fully understand the need of the code in elf_update. I
assume that is needed in case the file was used with ELF_C_RDWR_MMAP?
Cheers,
Mark
Hi Ying,
On Tue, May 16, 2023 at 03:34:01PM +0800, Ying Huang wrote:
> 在 2023/5/16 14:46, Ying Huang 写道:
> > >> 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.
> > > Where do these segfaults show up?
> > The screenshot of the segment error was not uploaded successfully in the last email, upload again.
Sorry, the mailinglist seems to strip the image attachements.
> huangying@Sleepygon:~/elf/elfutils_4$ src/elflint src/nm.o
> Segmentation fault
> huangying@Sleepygon:~/elf/elfutils_4$ src/elflint src/strip.o
> Segmentation fault
When running under gdb, what is the backtrace of the crash?
Thanks,
Mark
在 2023/5/22 05:13, Mark Wielaard 写道:
> Hi Ying,
>
> On Tue, May 16, 2023 at 02:38:45PM +0800, Ying Huang wrote:
>> 在 2023/5/9 23:15, Mark Wielaard 写道:
>>> On Tue, 2023-04-11 at 16:12 +0800, Ying Huang wrote:
>>>> 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.
>>> Is there a spec that describes this?
>>
>>
>> references:
>>
>> https://www.linux-mips.org/pub/linux/mips/doc/ABI/elf64-2.4.pdf
>>
>> Page40 && Page41
> Thanks. Interesting. If possible please include this URL in a comment.
OK.
>
>>> I see you adjusted elf.h to include:
>>>
>>> +#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)
>>>
>>> And various new relocation types for MIPS variants.
>>> Our elf.h comes from the glibc project. Have you also submitted these
>>> changes to libc-alpha@sourceware.org ?
>> Has submitted.
>>
>> https://sourceware.org/pipermail/libc-alpha/2023-May/148026.html
>>
>> https://sourceware.org/pipermail/libc-alpha/2023-May/148112.html
> Thanks. We'll sync them as soon as v3 lands.
>
>> Has tested on big/little endian machine with big/little endian
>> ELF file, all were OK.
> Could you post those ELF files somewhere?
> Maybe we can add some as test files?
The ELF files I used were "src/strip.o" which were generated on big/little endian machine.
root@debian-sid-mipsbe:~# readelf -h strip.o
ELF Header:
Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
Class: ELF64
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: REL (Relocatable file)
Machine: MIPS R3000
Version: 0x1
Entry point address: 0x0
Start of program headers: 0 (bytes into file)
Start of section headers: 426696 (bytes into file)
Flags: 0x80000007, noreorder, pic, cpic, mips64r2
Size of this header: 64 (bytes)
Size of program headers: 0 (bytes)
Number of program headers: 0
Size of section headers: 64 (bytes)
Number of section headers: 41
Section header string table index: 40
root@debian-sid-mipsbe:~# readelf -h elfutils_debug/src/strip.o
ELF Header:
Magic: 7f 45 4c 46 01 02 01 00 00 00 00 00 00 00 00 00
Class: ELF32
Data: 2's complement, big endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: REL (Relocatable file)
Machine: MIPS R3000
Version: 0x1
Entry point address: 0x0
Start of program headers: 0 (bytes into file)
Start of section headers: 215248 (bytes into file)
Flags: 0x70001007, noreorder, pic, cpic, o32, mips32r2
Size of this header: 52 (bytes)
Size of program headers: 0 (bytes)
Number of program headers: 0
Size of section headers: 40 (bytes)
Number of section headers: 40
Section header string table index: 39
root@debian-sid-mipsbe:~#
>>> It feels like this is in the wrong place and doesn't take into account
>>> whether the program itself is running on a big or little endian
>>> machine.
>>>
>>> Maybe I am misunderstanding why this conversion is needed always. But I
>>> would have expected a specific conversion function for MIPS for
>>> ELF_T_REL and/or ELF_T_RELA (which are currently generic).
>> 1.Considering that some people directly use the original data instead of the interface function gelf_getrela;
>>
>> 2.Because there is only one parameter, so can not modify the macro ELF64_R_TYPE;
>>
>> 3.If the mips interface function is added, other packages using libelf will not be compatible with mips, and the place where gelf_getrela is used need be modified.
>>
>> Where do you think is the most suitable place to do mips conversion?
> So for the convert_data case in elf_getdata.c I would expect a special
> conversion function being defined for ELF_T_REL and ELF_T_RELA. This
> normally comes from __elf_xfctstom. I realize now that cannot easily
> take an Elf of machine type. But I would expect to have the conversion
> be done by a new function that can be assigned to fp in convert_data:
>
> /* Get the conversion function. */
> fp = __elf_xfctstom[eclass - 1][type];
Maybe I can create a new function named "convert_data_for_mips" and contained the code that added in convert_data?
>
> I still don't fully understand the need of the code in elf_update. I
> assume that is needed in case the file was used with ELF_C_RDWR_MMAP?
>
> Cheers,
>
> Mark
Because we convert the relocation data for mips64el in elf_getdata.c, eg src/strip, and when we write elf to file, need confirm the relocation data is in original order bits.
When file use ELF_C_RDWR_MMAP, only impact whether malloc data_base in convert_data.
Thanks,
Ying
Hi Mark,
在 2023/5/22 05:14, Mark Wielaard 写道:
> Hi Ying,
>
> On Tue, May 16, 2023 at 03:34:01PM +0800, Ying Huang wrote:
>> 在 2023/5/16 14:46, Ying Huang 写道:
>>>>> 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.
>>>> Where do these segfaults show up?
>>> The screenshot of the segment error was not uploaded successfully in the last email, upload again.
> Sorry, the mailinglist seems to strip the image attachements.
>
>> huangying@Sleepygon:~/elf/elfutils_4$ src/elflint src/nm.o
>> Segmentation fault
>> huangying@Sleepygon:~/elf/elfutils_4$ src/elflint src/strip.o
>> Segmentation fault
> When running under gdb, what is the backtrace of the crash?
>
> Thanks,
>
> Mark
huangying@Sleepygon:~/elf/elfutils_4$ src/elflint src/nm.o
Segmentation fault (core dumped)
huangying@Sleepygon:~/elf/elfutils_4$ gdb src/elflint
...
(gdb) bt
#0 convert_data (type=ELF_T_RELA, size=24912, data=1, eclass=<optimized out>, scn=0xaad3698f98) at elf_getdata.c:254
#1 __libelf_set_data_list_rdlock (scn=0xaad3698f98, wrlocked=<optimized out>) at elf_getdata.c:515
#2 0x000000fff3862f14 in __elf_getdata_rdlock (scn=0xaad3698f98, data=<optimized out>) at elf_getdata.c:622
#3 0x000000fff3862f54 in elf_getdata (scn=<optimized out>, data=<optimized out>) at elf_getdata.c:640
#4 0x000000aaac571c9c in check_rela (ebl=0xaad369b120, ehdr=0xfffb9451b0, shdr=0xfffb945008, idx=<optimized out>) at elflint.c:1500
#5 0x000000aaac574e40 in check_sections (ebl=0xaad369b120, ehdr=0xfffb9451b0) at elflint.c:4198
#6 0x000000aaac5784ac in process_elf_file (only_one=<optimized out>, size=<optimized out>, fname=<optimized out>, suffix=<optimized out>, prefix=<optimized out>, elf=<optimized out>) at elflint.c:4842
#7 process_file (fd=<optimized out>, elf=<optimized out>, prefix=<optimized out>, suffix=<optimized out>, fname=<optimized out>, size=<optimized out>, only_one=<optimized out>) at elflint.c:241
#8 0x000000aaac5688fc in main (argc=<optimized out>, argv=0xfffb9455d8) at elflint.c:174
...
If I did not malloc to scn->data_base, would occur Segment fault when we want to operate this space "&scn->data_list.data.d". Because src/elflint use read-mmap method to map file.
Show 10 lines of code "libelf/elf_getdata.c" starting at line 254:
huangying@Sleepygon:~/elf/elfutils_4$ cat libelf/elf_getdata.c | tail -n +254 | head -n 10
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));
Show elflint map method in src/elflint.c:
/* Create an `Elf' descriptor. */
Elf *elf = elf_begin (fd, ELF_C_READ_MMAP, NULL);
Thanks,
Ying
@@ -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)
new file mode 100644
@@ -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 <http://www.gnu.org/licenses/>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#define BACKEND mips_
+#define RELOC_PREFIX R_MIPS_
+#include "libebl_CPU.h"
+
+/* 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;
+}
new file mode 100644
@@ -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 <http://www.gnu.org/licenses/>. */
+
+/* NAME, REL|EXEC|DYN */
+
+
+RELOC_TYPE (NONE, REL|EXEC|DYN)
+RELOC_TYPE (16, REL|EXEC|DYN)
+RELOC_TYPE (32, REL)
+RELOC_TYPE (REL32, REL|EXEC|DYN)
+RELOC_TYPE (26, REL|DYN)
+RELOC_TYPE (HI16, REL)
+RELOC_TYPE (LO16, REL|EXEC|DYN)
+RELOC_TYPE (GPREL16, REL|EXEC|DYN)
+RELOC_TYPE (LITERAL, REL|EXEC|DYN)
+RELOC_TYPE (GOT16, REL|EXEC|DYN)
+RELOC_TYPE (PC16, REL)
+RELOC_TYPE (CALL16, REL)
+RELOC_TYPE (GPREL32, REL)
+RELOC_TYPE (SHIFT5, REL)
+RELOC_TYPE (SHIFT6, REL)
+RELOC_TYPE (64, REL)
+RELOC_TYPE (GOT_DISP, REL)
+RELOC_TYPE (GOT_PAGE, REL)
+RELOC_TYPE (GOT_OFST, REL)
+RELOC_TYPE (GOT_HI16, REL)
+RELOC_TYPE (GOT_LO16, REL)
+RELOC_TYPE (SUB, REL)
+RELOC_TYPE (INSERT_A, REL)
+RELOC_TYPE (INSERT_B, REL)
+RELOC_TYPE (DELETE, REL)
+RELOC_TYPE (HIGHER, REL)
+RELOC_TYPE (HIGHEST, REL)
+RELOC_TYPE (CALL_HI16, REL)
+RELOC_TYPE (CALL_LO16, REL)
+RELOC_TYPE (SCN_DISP, REL)
+RELOC_TYPE (REL16, REL)
+RELOC_TYPE (ADD_IMMEDIATE, REL)
+RELOC_TYPE (PJUMP, REL)
+RELOC_TYPE (RELGOT, REL)
+RELOC_TYPE (JALR, REL)
+RELOC_TYPE (TLS_DTPMOD32, DYN)
+RELOC_TYPE (TLS_DTPREL32, REL)
+RELOC_TYPE (TLS_DTPMOD64, DYN)
+RELOC_TYPE (TLS_DTPREL64, REL)
+RELOC_TYPE (TLS_GD, REL)
+RELOC_TYPE (TLS_LDM, REL)
+RELOC_TYPE (TLS_DTPREL_HI16, REL)
+RELOC_TYPE (TLS_DTPREL_LO16, REL)
+RELOC_TYPE (TLS_GOTTPREL, REL)
+RELOC_TYPE (TLS_TPREL32, REL)
+RELOC_TYPE (TLS_TPREL64, REL)
+RELOC_TYPE (TLS_TPREL_HI16, REL)
+RELOC_TYPE (TLS_TPREL_LO16, REL)
+RELOC_TYPE (GLOB_DAT, REL)
+RELOC_TYPE (PC21_S2, REL)
+RELOC_TYPE (PC26_S2, REL)
+RELOC_TYPE (PC18_S3, REL)
+RELOC_TYPE (PC19_S2, REL)
+RELOC_TYPE (PCHI16, REL)
+RELOC_TYPE (PCLO16, REL)
+RELOC_TYPE (COPY, REL)
+RELOC_TYPE (JUMP_SLOT, REL)
+RELOC_TYPE (PC32, REL)
+RELOC_TYPE (EH, REL)
+RELOC_TYPE (GNU_REL16_S2, REL)
+RELOC_TYPE (GNU_VTINHERIT, REL)
+RELOC_TYPE (GNU_VTENTRY, REL)
new file mode 100644
@@ -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 <http://www.gnu.org/licenses/>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <system.h>
+
+#include <elf.h>
+#include <stddef.h>
+#include <string.h>
+#include <stdio.h>
+#define BACKEND mips_
+#include "libebl_CPU.h"
+#include "libelfP.h"
+/* Check for the simple reloc types. */
+Elf_Type
+mips_reloc_simple_type (Ebl *ebl, int type,
+ int *addsub __attribute__ ((unused)))
+{
+ int typeNew = type;
+ if(ebl->elf->class == ELFCLASS64)
+ typeNew = ELF64_MIPS_R_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;
+ }
+}
@@ -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]))
@@ -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. */
@@ -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;
+ }
+ }
+ }
}
@@ -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: