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 <ying.hu...@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. >> >> Signed-off-by: Ying Huang <ying.hu...@oss.cipunited.com> >> --- >> 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: