]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/commit
Fix objcopy for little-endian MIPS64 objects.
authorJohn Baldwin <jhb@FreeBSD.org>
Wed, 5 Sep 2018 20:51:53 +0000 (20:51 +0000)
committerJohn Baldwin <jhb@FreeBSD.org>
Wed, 5 Sep 2018 20:51:53 +0000 (20:51 +0000)
commiteb81f38a62c9ae246955feceedb8c043e78f871f
treef86b84554d1eaaef6f1d7f802ec461c2c26aa26f
parent0125fb63521b58780c41d9ded78ce175c8c5a7e0
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.

Discussed with: jkoshy
Reviewed by: emaste, imp
Approved by: re (gjb, kib)
MFC after: 1 month
Differential Revision: https://reviews.freebsd.org/D15734
contrib/elftoolchain/elfcopy/main.c
contrib/elftoolchain/libelf/Makefile
contrib/elftoolchain/libelf/_libelf.h
contrib/elftoolchain/libelf/gelf_mips64el.c [new file with mode: 0644]
contrib/elftoolchain/libelf/gelf_rel.c
contrib/elftoolchain/libelf/gelf_rela.c
sys/sys/param.h