eb81f38a62
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. Discussed with: jkoshy Reviewed by: emaste, imp Approved by: re (gjb, kib) MFC after: 1 month Differential Revision: https://reviews.freebsd.org/D15734 |
||
---|---|---|
.. | ||
_libelf_ar.h | ||
_libelf_config.h | ||
_libelf.h | ||
elf_begin.3 | ||
elf_begin.c | ||
elf_cntl.3 | ||
elf_cntl.c | ||
elf_data.c | ||
elf_end.3 | ||
elf_end.c | ||
elf_errmsg.3 | ||
elf_errmsg.c | ||
elf_errno.c | ||
elf_fill.3 | ||
elf_fill.c | ||
elf_flag.c | ||
elf_flagdata.3 | ||
elf_getarhdr.3 | ||
elf_getarhdr.c | ||
elf_getarsym.3 | ||
elf_getarsym.c | ||
elf_getbase.3 | ||
elf_getbase.c | ||
elf_getdata.3 | ||
elf_getident.3 | ||
elf_getident.c | ||
elf_getphdrnum.3 | ||
elf_getphnum.3 | ||
elf_getscn.3 | ||
elf_getshdrnum.3 | ||
elf_getshdrstrndx.3 | ||
elf_getshnum.3 | ||
elf_getshstrndx.3 | ||
elf_hash.3 | ||
elf_hash.c | ||
elf_kind.3 | ||
elf_kind.c | ||
elf_memory.3 | ||
elf_memory.c | ||
elf_next.3 | ||
elf_next.c | ||
elf_open.3 | ||
elf_open.c | ||
elf_phnum.c | ||
elf_rand.3 | ||
elf_rand.c | ||
elf_rawfile.3 | ||
elf_rawfile.c | ||
elf_scn.c | ||
elf_shnum.c | ||
elf_shstrndx.c | ||
elf_strptr.3 | ||
elf_strptr.c | ||
elf_types.m4 | ||
elf_update.3 | ||
elf_update.c | ||
elf_version.3 | ||
elf_version.c | ||
elf.3 | ||
elf.c | ||
gelf_cap.c | ||
gelf_checksum.3 | ||
gelf_checksum.c | ||
gelf_dyn.c | ||
gelf_ehdr.c | ||
gelf_fsize.3 | ||
gelf_fsize.c | ||
gelf_getcap.3 | ||
gelf_getclass.3 | ||
gelf_getclass.c | ||
gelf_getdyn.3 | ||
gelf_getehdr.3 | ||
gelf_getmove.3 | ||
gelf_getphdr.3 | ||
gelf_getrel.3 | ||
gelf_getrela.3 | ||
gelf_getshdr.3 | ||
gelf_getsym.3 | ||
gelf_getsyminfo.3 | ||
gelf_getsymshndx.3 | ||
gelf_mips64el.c | ||
gelf_move.c | ||
gelf_newehdr.3 | ||
gelf_newphdr.3 | ||
gelf_phdr.c | ||
gelf_rel.c | ||
gelf_rela.c | ||
gelf_shdr.c | ||
gelf_sym.c | ||
gelf_syminfo.c | ||
gelf_symshndx.c | ||
gelf_update_ehdr.3 | ||
gelf_xlate.c | ||
gelf_xlatetof.3 | ||
gelf.3 | ||
gelf.h | ||
libelf_align.c | ||
libelf_allocate.c | ||
libelf_ar_util.c | ||
libelf_ar.c | ||
libelf_checksum.c | ||
libelf_convert.m4 | ||
libelf_data.c | ||
libelf_ehdr.c | ||
libelf_extended.c | ||
libelf_fsize.m4 | ||
libelf_memory.c | ||
libelf_msize.m4 | ||
libelf_open.c | ||
libelf_phdr.c | ||
libelf_shdr.c | ||
libelf_xlate.c | ||
libelf.h | ||
Makefile | ||
os.FreeBSD.mk | ||
os.NetBSD.mk | ||
Version.map |