Bug 26542 - R_MIPS_16 operates on a 32-bit field
Summary: R_MIPS_16 operates on a 32-bit field
Alias: None
Product: binutils
Classification: Unclassified
Component: gas (show other bugs)
Version: 2.36
: P2 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
Depends on:
Reported: 2020-08-27 01:10 UTC by Alan Modra
Modified: 2020-08-27 01:44 UTC (History)
0 users

See Also:
Target: mipstx39-elf
Last reconfirmed:


Note You need to log in before you can comment on or make changes to this bug.
Description Alan Modra 2020-08-27 01:10:52 UTC
R_MIPS_16 has size=2 in reloc howto.  This would seem to disagree with the mips ABI which says the field is 16 bits.  Using the wrong size leads to an asan error when running the ld testsuite for mipstx39-elf

Executing on host: sh -c {./ld-new -z norelro  -L/home/alan/src/binutils-gdb/ld/testsuite/ld-mips-elf  -Tdata 0x10000 -e 0 -o tmpdir/dump tmpdir/reloc-localoverflow.o  2>&1}  /dev/null dump.tmp (timeout = 300)
spawn [open ...]
==12034==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x62100001c902 at pc 0x561697b97d27 bp 0x7fffe8f6a220 sp 0x7fffe8f6a210
READ of size 1 at 0x62100001c902 thread T0
    #0 0x561697b97d26 in bfd_getb32 /home/alan/src/binutils-gdb/bfd/libbfd.c:631
    #1 0x561697c12b46 in mips_elf_read_rel_addend /home/alan/src/binutils-gdb/bfd/elfxx-mips.c:8169

Correcting the size won't affect little-endian mips targets, but it would affect anyone who is currently using R_MIPS_16 on a big-endian target since defining the reloc as it is means on big-endian the field is at offset+2.

cat > short.s <<\EOF
 .short forword
 .short ext
 .short 0
gas/as-new -o short.o short.s
ld/ld-new -o short short.o --defsym ext=123 -Tdata=0x1000
binutils/objdump -s short

short:     file format elf32-bigmips

Contents of section .data:
 1000 00001000 007b                        .....{
Comment 1 Alan Modra 2020-08-27 01:30:04 UTC
Huh, no, on reading the ABI a little more carefully I see the half16 field is in fact in a 32-bit word.  So the reloc howto is OK but R_MIPS_16 can't really be used to relocate data on big-endian targets.
Comment 2 Alan Modra 2020-08-27 01:44:02 UTC
See also pr3243, which is probably the same bug but somewhat confused as to where the "R_MIPS_16 _memory_descriptors_size" reloc was applied.