Sorry, the diff has some formatting issues. And the test results use the
existing patches 2/6 3/6 4/6.
diff --git a/libelf/gelf_getrela.c b/libelf/gelf_getrela.c index
d695f659..fd974bdf 100644 --- a/libelf/gelf_getrela.c +++
b/libelf/gelf_getrela.c @@ -90,8 +90,21 @@ gelf_getrela (Elf_Data *data, int
ndx, GElf_Rela *dst) result = NULL; } else - result = memcpy (dst,
&((Elf64_Rela *) data_scn->d.d_buf)[ndx], - sizeof (Elf64_Rela)); + { + result
= memcpy (dst, &((Elf64_Rela *) data_scn->d.d_buf)[ndx], + sizeof
(Elf64_Rela)); + GElf_Ehdr ehdr_mem; + GElf_Ehdr *ehdr = __gelf_getehdr_rdlock
(scn->elf, &ehdr_mem); + if(ehdr != NULL && ehdr->e_machine == EM_MIPS &&
ehdr->e_ident[EI_DATA] == ELFDATA2LSB) + { + Elf64_Xword info = dst->r_info; +
dst->r_info = (((info & 0xffffffff) << 32) + | ((info >> 56) & 0xff) + | ((info
>> 40) & 0xff00) + | ((info >> 24) & 0xff0000) + | ((info >> 8) & 0xff000000));
+ } + } } rwlock_unlock (scn->elf->lock); diff --git
a/libelf/gelf_update_rela.c b/libelf/gelf_update_rela.c index
88252703..592d74b9 100644 --- a/libelf/gelf_update_rela.c +++
b/libelf/gelf_update_rela.c @@ -96,7 +96,20 @@ gelf_update_rela (Elf_Data *dst,
int ndx, GElf_Rela *src) goto out; } - ((Elf64_Rela *) data_scn->d.d_buf)[ndx]
= *src; + GElf_Ehdr ehdr_mem; + GElf_Ehdr *ehdr = __gelf_getehdr_rdlock
(scn->elf, &ehdr_mem); + GElf_Rela rela = *src; + if(ehdr != NULL &&
ehdr->e_machine == EM_MIPS && ehdr->e_ident[EI_DATA] == ELFDATA2LSB) + { +
Elf64_Xword info = rela.r_info; + rela.r_info = (info >> 32 + | ((info << 56) &
0xff00000000000000) + | ((info << 40) & 0xff000000000000) + | ((info << 24) &
0xff0000000000) + | ((info << 8) & 0xff00000000)); + } + + ((Elf64_Rela *)
data_scn->d.d_buf)[ndx] = rela; } result = 1;
在 2024/7/10 10:37, Ying Huang 写道:
> Hi Mark,
>
> I have done tests on mips32 littele/big endian and mips64 little
> endian(because now I did not have mips64 big endian lab).
>
> Attached are the test results and I compared them.
>
> This is the change I mentioned last time to replace file
> libelf/elf_getdata.c. What do you think of this change?
>
> /*diff --git a/libelf/gelf_getrela.c b/libelf/gelf_getrela.c index
> d695f659..fd974bdf 100644 --- a/libelf/gelf_getrela.c +++
> b/libelf/gelf_getrela.c @@ -90,8 +90,21 @@ gelf_getrela (Elf_Data *data, int
> ndx, GElf_Rela *dst) result = NULL; } else - result = memcpy (dst,
> &((Elf64_Rela *) data_scn->d.d_buf)[ndx], - sizeof (Elf64_Rela)); + { +
> result = memcpy (dst, &((Elf64_Rela *) data_scn->d.d_buf)[ndx], + sizeof
> (Elf64_Rela)); + GElf_Ehdr ehdr_mem; + GElf_Ehdr *ehdr =
> __gelf_getehdr_rdlock (scn->elf, &ehdr_mem); + if(ehdr != NULL &&
> ehdr->e_machine == EM_MIPS && ehdr->e_ident[EI_DATA] == ELFDATA2LSB) + { +
> Elf64_Xword info = dst->r_info; + dst->r_info = (((info & 0xffffffff) << 32)
> + | ((info >> 56) & 0xff) + | ((info >> 40) & 0xff00) + | ((info >> 24) &
> 0xff0000) + | ((info >> 8) & 0xff000000)); + } + } }*/ /*rwlock_unlock
> (scn->elf->lock);*/
>
> /*diff --git a/libelf/gelf_update_rela.c b/libelf/gelf_update_rela.c index
> 88252703..592d74b9 100644 --- a/libelf/gelf_update_rela.c +++
> b/libelf/gelf_update_rela.c @@ -96,7 +96,20 @@ gelf_update_rela (Elf_Data
> *dst, int ndx, GElf_Rela *src) goto out; } - ((Elf64_Rela *)
> data_scn->d.d_buf)[ndx] = *src; + GElf_Ehdr ehdr_mem; + GElf_Ehdr *ehdr =
> __gelf_getehdr_rdlock (scn->elf, &ehdr_mem); + GElf_Rela rela = *src; +
> if(ehdr != NULL && ehdr->e_machine == EM_MIPS && ehdr->e_ident[EI_DATA] ==
> ELFDATA2LSB) + { + Elf64_Xword info = rela.r_info; + rela.r_info = (info >>
> 32 + | ((info << 56) & 0xff00000000000000) + | ((info << 40) &
> 0xff000000000000) + | ((info << 24) & 0xff0000000000) + | ((info << 8) &
> 0xff00000000)); + } + + ((Elf64_Rela *) data_scn->d.d_buf)[ndx] = rela; }
> result = 1;*/
>
> 1. Target: mips64el-linux-gnuabi64
>
> huangying@Sleepygon:~/elf/elfutils_main$ cat mips64el_with_patch.log | grep
> FAIL
> # XFAIL: 0
> # FAIL: 1
> FAIL: run-sysroot.sh
> FAIL run-sysroot.sh (exit status: 1)
>
> -------This failed test case is related to src/stack and was investigating.
>
> huangying@Sleepygon:~/elf/elfutils_main$ cat mips64el_without_patch.log |
> grep FAIL
> # XFAIL: 0
> # FAIL: 7
> FAIL: run-strip-strmerge.sh
> FAIL run-strip-strmerge.sh (exit status: 1)
> FAIL: run-strip-reloc-self.sh
> FAIL run-strip-reloc-self.sh (exit status: 1)
> FAIL: run-elflint-self.sh
> FAIL run-elflint-self.sh (exit status: 1)
> FAIL: run-varlocs-self.sh
> FAIL run-varlocs-self.sh (exit status: 1)
> FAIL: run-exprlocs-self.sh
> FAIL run-exprlocs-self.sh (exit status: 1)
> FAIL: run-reverse-sections-self.sh
> FAIL run-reverse-sections-self.sh (exit status: 1)
> FAIL: run-sysroot.sh
> FAIL run-sysroot.sh (exit status: 1)
>
>
> 2. Target: mipsel-linux-gnu:
>
> root@debian-sid-mipsel:~/elfutils_6# cat mips32el_with_patch.log | grep FAIL
> # XFAIL: 0
> # FAIL: 10
> FAIL: run-bug1-test.sh
> FAIL run-bug1-test.sh (exit status: 1)
> FAIL: run-backtrace-native.sh
> FAIL run-backtrace-native.sh (exit status: 1)
> FAIL: run-backtrace-dwarf.sh
> FAIL run-backtrace-dwarf.sh (exit status: 1)
> FAIL: run-backtrace-native-core.sh
> FAIL run-backtrace-native-core.sh (exit status: 1)
> FAIL: run-deleted.sh
> FAIL run-deleted.sh (exit status: 1)
> FAIL: elfstrtab
> FAIL elfstrtab (exit status: 1)
> FAIL: dwfl-proc-attach
> FAIL dwfl-proc-attach (exit status: 255)
> FAIL: emptyfile
> FAIL emptyfile (exit status: 1)
> FAIL: run-copyadd-sections.sh
> FAIL run-copyadd-sections.sh (exit status: 1)
> FAIL: run-sysroot.sh
> FAIL run-sysroot.sh (exit status: 1)
>
> --------These failed test cases are because the docker container does not
> support some features.
>
> root@debian-sid-mipsel:~/elfutils_6# cat mips32el_without_patch.log | grep
> FAIL
> # XFAIL: 0
> # FAIL: 14
> *FAIL: run-strip-strmerge.sh
> FAIL run-strip-strmerge.sh (exit status: 1)
> FAIL: run-strip-reloc-self.sh
> FAIL run-strip-reloc-self.sh (exit status: 1)
> FAIL: run-elflint-self.sh
> FAIL run-elflint-self.sh (exit status: 1)*
> FAIL: run-bug1-test.sh
> FAIL run-bug1-test.sh (exit status: 1)
> FAIL: run-backtrace-native.sh
> FAIL run-backtrace-native.sh (exit status: 1)
> FAIL: run-backtrace-dwarf.sh
> FAIL run-backtrace-dwarf.sh (exit status: 1)
> FAIL: run-backtrace-native-core.sh
> FAIL run-backtrace-native-core.sh (exit status: 1)
> FAIL: run-deleted.sh
> FAIL run-deleted.sh (exit status: 1)
> FAIL: elfstrtab
> FAIL elfstrtab (exit status: 1)
> FAIL: dwfl-proc-attach
> FAIL dwfl-proc-attach (exit status: 255)
> FAIL: emptyfile
> FAIL emptyfile (exit status: 1)
> *FAIL: run-reverse-sections-self.sh
> FAIL run-reverse-sections-self.sh (exit status: 1)*
> FAIL: run-copyadd-sections.sh
> FAIL run-copyadd-sections.sh (exit status: 1)
> FAIL: run-sysroot.sh
> FAIL run-sysroot.sh (exit status: 1)
>
>
> 3. Target: mips-linux-gnu
>
> root@debian-sid-mipsbe:~/elfutils_main# cat mips32be_with_patch.log | grep
> FAIL
> # XFAIL: 0
> # FAIL: 11
> FAIL: run-native-test.sh
> FAIL run-native-test.sh (exit status: 1)
> FAIL: run-bug1-test.sh
> FAIL run-bug1-test.sh (exit status: 1)
> FAIL: run-backtrace-native.sh
> FAIL run-backtrace-native.sh (exit status: 1)
> FAIL: run-backtrace-dwarf.sh
> FAIL run-backtrace-dwarf.sh (exit status: 1)
> FAIL: run-backtrace-native-core.sh
> FAIL run-backtrace-native-core.sh (exit status: 1)
> FAIL: run-deleted.sh
> FAIL run-deleted.sh (exit status: 1)
> FAIL: elfstrtab
> FAIL elfstrtab (exit status: 1)
> FAIL: dwfl-proc-attach
> FAIL dwfl-proc-attach (exit status: 255)
> FAIL: emptyfile
> FAIL emptyfile (exit status: 1)
> FAIL: run-copyadd-sections.sh
> FAIL run-copyadd-sections.sh (exit status: 1)
> FAIL: run-sysroot.sh
> FAIL run-sysroot.sh (exit status: 1)
> root@debian-sid-mipsbe:~/elfutils_main# cat mips32be_without_patch.log | grep
> FAIL
> # XFAIL: 0
> # FAIL: 15
> *FAIL: run-strip-strmerge.sh
> FAIL run-strip-strmerge.sh (exit status: 1)
> FAIL: run-strip-reloc-self.sh
> FAIL run-strip-reloc-self.sh (exit status: 1)
> FAIL: run-elflint-self.sh
> FAIL run-elflint-self.sh (exit status: 1)*
> FAIL: run-native-test.sh
> FAIL run-native-test.sh (exit status: 1)
> FAIL: run-bug1-test.sh
> FAIL run-bug1-test.sh (exit status: 1)
> FAIL: run-backtrace-native.sh
> FAIL run-backtrace-native.sh (exit status: 1)
> FAIL: run-backtrace-dwarf.sh
> FAIL run-backtrace-dwarf.sh (exit status: 1)
> FAIL: run-backtrace-native-core.sh
> FAIL run-backtrace-native-core.sh (exit status: 1)
> FAIL: run-deleted.sh
> FAIL run-deleted.sh (exit status: 1)
> FAIL: elfstrtab
> FAIL elfstrtab (exit status: 1)
> FAIL: dwfl-proc-attach
> FAIL dwfl-proc-attach (exit status: 255)
> FAIL: emptyfile
> FAIL emptyfile (exit status: 1)
> *FAIL: run-reverse-sections-self.sh
> FAIL run-reverse-sections-self.sh (exit status: 1)*
> FAIL: run-copyadd-sections.sh
> FAIL run-copyadd-sections.sh (exit status: 1)
> FAIL: run-sysroot.sh
> FAIL run-sysroot.sh (exit status: 1)
>
> Thanks,
>
> Ying
>
>
> 在 2024/3/5 17:51, Ying Huang 写道:
>> From: Ying Huang <[email protected]>
>>
>> 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.
>>
>> Signed-off-by: Ying Huang <[email protected]>
>> ---
>> libelf/elf_getdata.c | 132 ++++++++++++++++++++++++++++++++++++++++++-
>> libelf/elf_update.c | 53 +++++++++++++++++
>> 2 files changed, 183 insertions(+), 2 deletions(-)
>>
>> diff --git a/libelf/elf_getdata.c b/libelf/elf_getdata.c
>> index 7c3ac043..942ba536 100644
>> --- a/libelf/elf_getdata.c
>> +++ b/libelf/elf_getdata.c
>> @@ -133,6 +133,119 @@ __libelf_data_type (GElf_Ehdr *ehdr, int sh_type,
>> GElf_Xword align)
>> }
>> }
>>
>> +/* Convert the data in the current section. */
>> +static void
>> +convert_data_for_mips64el (Elf_Scn *scn, int eclass,
>> + int data, size_t size, Elf_Type type)
>> +{
>> + /* Do we need to convert the data and/or adjust for alignment? */
>> + if (data == MY_ELFDATA || type == ELF_T_BYTE)
>> + {
>> + /* 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. */
>> + 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
>> + {
>> + xfct_t fp;
>> +
>> + scn->data_base = malloc (size);
>> + if (scn->data_base == NULL)
>> + {
>> + __libelf_seterrno (ELF_E_NOMEM);
>> + return;
>> + }
>> +
>> + /* Make sure the source is correctly aligned for the conversion
>> + function to directly access the data elements. */
>> + char *rawdata_source;
>> + /* 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. */
>> + 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);
>> +
>> + /* Get the conversion function. */
>> + fp = __elf_xfctstom[eclass - 1][type];
>> +
>> + fp (scn->data_base, rawdata_source, size, 0);
>> +
>> + if (rawdata_source != scn->rawdata_base)
>> + free (rawdata_source);
>> + }
>> +
>> + scn->data_list.data.d.d_buf = scn->data_base;
>> + scn->data_list.data.d.d_size = size;
>> + scn->data_list.data.d.d_type = type;
>> + scn->data_list.data.d.d_off = scn->rawdata.d.d_off;
>> + scn->data_list.data.d.d_align = scn->rawdata.d.d_align;
>> + 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. */
>> + /* references:
>> + https://www.linux-mips.org/pub/linux/mips/doc/ABI/elf64-2.4.pdf
>> + Page40 && Page41 */
>> + GElf_Shdr shdr_mem;
>> + GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
>> + 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;
>> + }
>> + }
>> +}
>> +
>> /* Convert the data in the current section. */
>> static void
>> convert_data (Elf_Scn *scn, int eclass,
>> @@ -451,8 +564,23 @@ __libelf_set_data_list_rdlock (Elf_Scn *scn, int
>> wrlocked)
>> return;
>> }
>>
>> - /* Convert according to the version and the type. */
>> - convert_data (scn, elf->class,
>> + 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)
>> + convert_data_for_mips64el (scn, elf->class,
>> + (elf->class == ELFCLASS32
>> + || (offsetof (struct Elf, state.elf32.ehdr)
>> + == offsetof (struct Elf, state.elf64.ehdr))
>> + ? elf->state.elf32.ehdr->e_ident[EI_DATA]
>> + : elf->state.elf64.ehdr->e_ident[EI_DATA]),
>> + scn->rawdata.d.d_size, scn->rawdata.d.d_type);
>> + else
>> + /* Convert according to the version and the type. */
>> + convert_data (scn, elf->class,
>> (elf->class == ELFCLASS32
>> || (offsetof (struct Elf, state.elf32.ehdr)
>> == offsetof (struct Elf, state.elf64.ehdr))
>> diff --git a/libelf/elf_update.c b/libelf/elf_update.c
>> index 56af3a1c..aec19b7c 100644
>> --- a/libelf/elf_update.c
>> +++ b/libelf/elf_update.c
>> @@ -228,7 +228,60 @@ elf_update (Elf *elf, Elf_Cmd cmd)
>> size = -1;
>> }
>> else
>> + {
>> + /* Because we converted the relocation info in mips order when we
>> call elf_getdata.c,
>> + so we need to convert the modified data in original order bits
>> before writing the
>> + data to the file. */
>> + Elf_Scn *scn = NULL;
>> + while ((scn = elf_nextscn (elf, scn)) != NULL)
>> + {
>> + GElf_Shdr shdr_mem;
>> + GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
>> + GElf_Ehdr ehdr_mem;
>> + GElf_Ehdr *ehdr = gelf_getehdr (scn->elf, &ehdr_mem);
>> + if (shdr != NULL && (shdr->sh_type == SHT_RELA || shdr->sh_type
>> == SHT_REL) &&
>> + scn->elf->class == ELFCLASS64 &&
>> + ehdr != NULL && ehdr->e_machine == EM_MIPS &&
>> ehdr->e_ident[EI_DATA] == ELFDATA2LSB)
>> + {
>> + Elf_Data *d = elf_getdata (scn, NULL);
>> + if (shdr->sh_type == SHT_REL)
>> + {
>> + size_t sh_entsize = gelf_fsize (scn->elf, ELF_T_REL, 1,
>> EV_CURRENT);
>> + int nentries = shdr->sh_size / sh_entsize;
>> + for (int cnt = 0; cnt < nentries; ++cnt)
>> + {
>> + Elf_Data_Scn *data_scn = (Elf_Data_Scn *) d;
>> + Elf64_Rel *value = &((Elf64_Rel *)
>> data_scn->d.d_buf)[cnt];
>> + Elf64_Xword info = value->r_info;
>> + value->r_info = (info >> 32
>> + | ((info << 56) & 0xff00000000000000)
>> + | ((info << 40) & 0xff000000000000)
>> + | ((info << 24) & 0xff0000000000)
>> + | ((info << 8) & 0xff00000000));
>> + ((Elf64_Rel *) data_scn->d.d_buf)[cnt] = *value;
>> + }
>> + }
>> + else if (shdr->sh_type == SHT_RELA)
>> + {
>> + size_t sh_entsize = gelf_fsize (scn->elf, ELF_T_RELA, 1,
>> EV_CURRENT);
>> + int nentries = shdr->sh_size / sh_entsize;
>> + for (int cnt = 0; cnt < nentries; cnt++)
>> + {
>> + Elf_Data_Scn *data_scn = (Elf_Data_Scn *) d;
>> + Elf64_Rela *value = &((Elf64_Rela *)
>> data_scn->d.d_buf)[cnt];
>> + Elf64_Xword info = value->r_info;
>> + value->r_info = (info >> 32
>> + | ((info << 56) & 0xff00000000000000)
>> + | ((info << 40) & 0xff000000000000)
>> + | ((info << 24) & 0xff0000000000)
>> + | ((info << 8) & 0xff00000000));
>> + ((Elf64_Rela *) data_scn->d.d_buf)[cnt] = *value;
>> + }
>> + }
>> + }
>> + }
>> size = write_file (elf, size, change_bo, shnum);
>> + }
>> }
>>
>> out: