svn commit: r340309 - in stable/11: contrib/elftoolchain/elfcopy contrib/elftoolchain/libelf sys/sys
Ed Maste
emaste at FreeBSD.org
Fri Nov 9 21:45:45 UTC 2018
Author: emaste
Date: Fri Nov 9 21:45:42 2018
New Revision: 340309
URL: https://svnweb.freebsd.org/changeset/base/340309
Log:
Fix objcopy for little-endian MIPS64 objects.
MFC r338478 (jhb): Fix objcopy for little-endian MIPS64 objects.
MIPS64 does not store the 'r_info' field of a relocation table entry as
a 64-bit value consisting of a 32-bit symbol index in the high 32 bits
and a 32-bit type in the low 32 bits as on other architectures. Instead,
the 64-bit 'r_info' field is really a 32-bit symbol index followed by four
individual byte type fields. For big-endian MIPS64, treating this as a
64-bit integer happens to be compatible with the layout expected by other
architectures (symbol index in upper 32-bits of resulting "native" 64-bit
integer). However, for little-endian MIPS64 the parsed 64-bit integer
contains the symbol index in the low 32 bits and the 4 individual byte
type fields in the upper 32-bits (but as if the upper 32-bits were
byte-swapped).
To cope, add two helper routines in gelf_getrel.c to translate between the
correct native 'r_info' value and the value obtained after the normal
byte-swap translation. Use these routines in gelf_getrel(), gelf_getrela(),
gelf_update_rel(), and gelf_update_rela(). This fixes 'readelf -r' on
little-endian MIPS64 objects which was previously decoding incorrect
relocations as well as 'objcopy: invalid symbox index' warnings from
objcopy when extracting debug symbols from kernel modules.
Even with this fixed, objcopy was still crashing when trying to extract
debug symbols from little-endian MIPS64 modules. The workaround in
gelf_*rel*() depends on the current ELF object having a valid ELF header
so that the 'e_machine' field can be compared against EM_MIPS. objcopy
was parsing the relocation entries to possibly rewrite the 'r_info' fields
in the update_relocs() function before writing the initial ELF header to
the destination object file. Move the initial write of the ELF header
earlier before copy_contents() so that update_relocs() uses the correct
symbol index values.
Note that this change should really go upstream. The binutils readelf
source has a similar hack for MIPS64EL though I implemented this version
from scratch using the MIPS64 ABI PDF as a reference.
MFC r339083 (emaste): libelf: correct mips64el test to use ELF header
libelf maintains two views of endianness: e_byteorder, and
e_ident[EI_DATA] in the ELF header itself. e_byteorder is not always
kept in sync, so use the ELF header endianness to test for mips64el.
MFC r339473 (emaste): libelf: also test for 64-bit ELF in _libelf_is_mips64el
Although _libelf_is_mips64el is only called in contexts where we've
already checked that e_class is ELFCLASS64 but this may change in the
future. Add a safety belt so that we don't access an invalid e_ehdr64
union member if it does.
PR: 231790
Added:
stable/11/contrib/elftoolchain/libelf/gelf_mips64el.c
- copied, changed from r338478, head/contrib/elftoolchain/libelf/gelf_mips64el.c
Modified:
stable/11/contrib/elftoolchain/elfcopy/main.c
stable/11/contrib/elftoolchain/libelf/Makefile
stable/11/contrib/elftoolchain/libelf/_libelf.h
stable/11/contrib/elftoolchain/libelf/gelf_rel.c
stable/11/contrib/elftoolchain/libelf/gelf_rela.c
stable/11/sys/sys/param.h
Directory Properties:
stable/11/ (props changed)
Modified: stable/11/contrib/elftoolchain/elfcopy/main.c
==============================================================================
--- stable/11/contrib/elftoolchain/elfcopy/main.c Fri Nov 9 21:41:23 2018 (r340308)
+++ stable/11/contrib/elftoolchain/elfcopy/main.c Fri Nov 9 21:45:42 2018 (r340309)
@@ -372,6 +372,14 @@ create_elf(struct elfcopy *ecp)
create_symtab(ecp);
/*
+ * Write the underlying ehdr. Note that it should be called
+ * before elf_setshstrndx() since it will overwrite e->e_shstrndx.
+ */
+ if (gelf_update_ehdr(ecp->eout, &oeh) == 0)
+ errx(EXIT_FAILURE, "gelf_update_ehdr() failed: %s",
+ elf_errmsg(-1));
+
+ /*
* First processing of output sections: at this stage we copy the
* content of each section from input to output object. Section
* content will be modified and printed (mcs) if need. Also content of
@@ -379,14 +387,6 @@ create_elf(struct elfcopy *ecp)
* to symbol table changes.
*/
copy_content(ecp);
-
- /*
- * Write the underlying ehdr. Note that it should be called
- * before elf_setshstrndx() since it will overwrite e->e_shstrndx.
- */
- if (gelf_update_ehdr(ecp->eout, &oeh) == 0)
- errx(EXIT_FAILURE, "gelf_update_ehdr() failed: %s",
- elf_errmsg(-1));
/* Generate section name string table (.shstrtab). */
set_shstrtab(ecp);
Modified: stable/11/contrib/elftoolchain/libelf/Makefile
==============================================================================
--- stable/11/contrib/elftoolchain/libelf/Makefile Fri Nov 9 21:41:23 2018 (r340308)
+++ stable/11/contrib/elftoolchain/libelf/Makefile Fri Nov 9 21:45:42 2018 (r340309)
@@ -35,6 +35,7 @@ SRCS= elf.c \
gelf_ehdr.c \
gelf_getclass.c \
gelf_fsize.c \
+ gelf_mips64el.c \
gelf_move.c \
gelf_phdr.c \
gelf_rel.c \
Modified: stable/11/contrib/elftoolchain/libelf/_libelf.h
==============================================================================
--- stable/11/contrib/elftoolchain/libelf/_libelf.h Fri Nov 9 21:41:23 2018 (r340308)
+++ stable/11/contrib/elftoolchain/libelf/_libelf.h Fri Nov 9 21:45:42 2018 (r340309)
@@ -216,12 +216,15 @@ int (*_libelf_get_translator(Elf_Type _t, int _directi
void *_libelf_getphdr(Elf *_e, int _elfclass);
void *_libelf_getshdr(Elf_Scn *_scn, int _elfclass);
void _libelf_init_elf(Elf *_e, Elf_Kind _kind);
+int _libelf_is_mips64el(Elf *e);
int _libelf_load_section_headers(Elf *e, void *ehdr);
unsigned int _libelf_malign(Elf_Type _t, int _elfclass);
Elf *_libelf_memory(unsigned char *_image, size_t _sz, int _reporterror);
size_t _libelf_msize(Elf_Type _t, int _elfclass, unsigned int _version);
void *_libelf_newphdr(Elf *_e, int _elfclass, size_t _count);
Elf *_libelf_open_object(int _fd, Elf_Cmd _c, int _reporterror);
+Elf64_Xword _libelf_mips64el_r_info_tof(Elf64_Xword r_info);
+Elf64_Xword _libelf_mips64el_r_info_tom(Elf64_Xword r_info);
struct _Libelf_Data *_libelf_release_data(struct _Libelf_Data *_d);
Elf *_libelf_release_elf(Elf *_e);
Elf_Scn *_libelf_release_scn(Elf_Scn *_s);
Copied and modified: stable/11/contrib/elftoolchain/libelf/gelf_mips64el.c (from r338478, head/contrib/elftoolchain/libelf/gelf_mips64el.c)
==============================================================================
--- head/contrib/elftoolchain/libelf/gelf_mips64el.c Wed Sep 5 20:51:53 2018 (r338478, copy source)
+++ stable/11/contrib/elftoolchain/libelf/gelf_mips64el.c Fri Nov 9 21:45:42 2018 (r340309)
@@ -34,8 +34,9 @@ int
_libelf_is_mips64el(Elf *e)
{
- return (e->e_kind == ELF_K_ELF && e->e_byteorder == ELFDATA2LSB &&
- e->e_u.e_elf.e_ehdr.e_ehdr64->e_machine == EM_MIPS);
+ return (e->e_kind == ELF_K_ELF && e->e_class == ELFCLASS64 &&
+ e->e_u.e_elf.e_ehdr.e_ehdr64->e_machine == EM_MIPS &&
+ e->e_u.e_elf.e_ehdr.e_ehdr64->e_ident[EI_DATA] == ELFDATA2LSB);
}
/*
Modified: stable/11/contrib/elftoolchain/libelf/gelf_rel.c
==============================================================================
--- stable/11/contrib/elftoolchain/libelf/gelf_rel.c Fri Nov 9 21:41:23 2018 (r340308)
+++ stable/11/contrib/elftoolchain/libelf/gelf_rel.c Fri Nov 9 21:45:42 2018 (r340309)
@@ -90,6 +90,9 @@ gelf_getrel(Elf_Data *ed, int ndx, GElf_Rel *dst)
rel64 = (Elf64_Rel *) d->d_data.d_buf + ndx;
*dst = *rel64;
+
+ if (_libelf_is_mips64el(e))
+ dst->r_info = _libelf_mips64el_r_info_tom(rel64->r_info);
}
return (dst);
@@ -156,6 +159,9 @@ gelf_update_rel(Elf_Data *ed, int ndx, GElf_Rel *dr)
rel64 = (Elf64_Rel *) d->d_data.d_buf + ndx;
*rel64 = *dr;
+
+ if (_libelf_is_mips64el(e))
+ rel64->r_info = _libelf_mips64el_r_info_tof(dr->r_info);
}
return (1);
Modified: stable/11/contrib/elftoolchain/libelf/gelf_rela.c
==============================================================================
--- stable/11/contrib/elftoolchain/libelf/gelf_rela.c Fri Nov 9 21:41:23 2018 (r340308)
+++ stable/11/contrib/elftoolchain/libelf/gelf_rela.c Fri Nov 9 21:45:42 2018 (r340309)
@@ -91,6 +91,10 @@ gelf_getrela(Elf_Data *ed, int ndx, GElf_Rela *dst)
rela64 = (Elf64_Rela *) d->d_data.d_buf + ndx;
*dst = *rela64;
+
+ if (_libelf_is_mips64el(e))
+ dst->r_info =
+ _libelf_mips64el_r_info_tom(rela64->r_info);
}
return (dst);
@@ -159,6 +163,9 @@ gelf_update_rela(Elf_Data *ed, int ndx, GElf_Rela *dr)
rela64 = (Elf64_Rela *) d->d_data.d_buf + ndx;
*rela64 = *dr;
+
+ if (_libelf_is_mips64el(e))
+ rela64->r_info = _libelf_mips64el_r_info_tof(dr->r_info);
}
return (1);
Modified: stable/11/sys/sys/param.h
==============================================================================
--- stable/11/sys/sys/param.h Fri Nov 9 21:41:23 2018 (r340308)
+++ stable/11/sys/sys/param.h Fri Nov 9 21:45:42 2018 (r340309)
@@ -58,7 +58,7 @@
* in the range 5 to 9.
*/
#undef __FreeBSD_version
-#define __FreeBSD_version 1102503 /* Master, propagated to newvers */
+#define __FreeBSD_version 1102504 /* Master, propagated to newvers */
/*
* __FreeBSD_kernel__ indicates that this system uses the kernel of FreeBSD,
More information about the svn-src-all
mailing list