Bug 14097 - Gold doesn't check R_X86_64_RELATIVE64 addend overflow
Summary: Gold doesn't check R_X86_64_RELATIVE64 addend overflow
Status: NEW
Alias: None
Product: binutils
Classification: Unclassified
Component: gold (show other bugs)
Version: 2.24
: P2 normal
Target Milestone: ---
Assignee: Ian Lance Taylor
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2012-05-11 11:42 UTC by H.J. Lu
Modified: 2012-05-11 12:04 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description H.J. Lu 2012-05-11 11:42:21 UTC
R_X86_64_RELATIVE64 addend is 32-bit and can overflow.
Gold failed to check it:

[hjl@gnu-6 gold]$ cat tst-quadmod4.S
	.section	.data.rel.local,"aw",@progbits
	.align 8
.Ljmp:
	.quad	func + 0x7fffffff

	.text
	.type	func, @function
func:
	ret
[hjl@gnu-6 gold]$ make bad LD=./ld.gold
gcc -B./ -mx32 -c -g -o tst-quadmod4.o tst-quadmod4.S
./ld.gold -shared -m elf32_x86_64 -o libtst-quadmod4.so tst-quadmod4.o
readelf -r --wide tst-quadmod4.o

Relocation section '.rela.data.rel.local' at offset 0x4c8 contains 1 entries:
 Offset     Info    Type                Sym. Value  Symbol's Name + Addend
00000000  00000101 R_X86_64_64            00000000   .text + 7fffffff

Relocation section '.rela.debug_line' at offset 0x4d4 contains 1 entries:
 Offset     Info    Type                Sym. Value  Symbol's Name + Addend
00000032  0000010a R_X86_64_32            00000000   .text + 0

Relocation section '.rela.debug_info' at offset 0x4e0 contains 4 entries:
 Offset     Info    Type                Sym. Value  Symbol's Name + Addend
00000006  0000070a R_X86_64_32            00000000   .debug_abbrev + 0
0000000c  0000080a R_X86_64_32            00000000   .debug_line + 0
00000010  0000010a R_X86_64_32            00000000   .text + 0
00000014  0000010a R_X86_64_32            00000000   .text + 1

Relocation section '.rela.debug_aranges' at offset 0x510 contains 2 entries:
 Offset     Info    Type                Sym. Value  Symbol's Name + Addend
00000006  0000060a R_X86_64_32            00000000   .debug_info + 0
00000010  0000010a R_X86_64_32            00000000   .text + 0
readelf -r --wide libtst-quadmod4.so

Relocation section '.rela.dyn' at offset 0x134 contains 1 entries:
 Offset     Info    Type                Sym. Value  Symbol's Name + Addend
000011c0  00000026 R_X86_64_RELATIVE64               -7ffffec1
[hjl@gnu-6 gold]$ 

When gold generates R_X86_64_RELATIVE64 for R_X86_64_64,
it changes the sign of addend.  BFD linker issues an error:

[hjl@gnu-6 gold]$ ./ld.bfd -shared -m elf32_x86_64 -o libtst-quadmod4.so tst-quadmod4.o
./ld.bfd: tst-quadmod4.o: addend 0x7fffffff in relocation R_X86_64_64 against symbol `.text' at 0x0 in section `.data.rel.local' is out of range
./ld.bfd: final link failed: Bad value
[hjl@gnu-6 gold]$
Comment 1 H.J. Lu 2012-05-11 12:04:09 UTC
Addend overflow can be seen in

template<bool dynamic, int size, bool big_endian>
void
Output_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>::write(
    unsigned char* pov) const
{
  elfcpp::Rela_write<size, big_endian> orel(pov);
  this->rel_.write_rel(&orel);
  Addend addend = this->addend_;
  if (this->rel_.is_target_specific())
    addend = parameters->target().reloc_addend(this->rel_.target_arg(),
                                               this->rel_.type(), addend);
  else if (this->rel_.is_symbolless())
    addend = this->rel_.symbol_value(addend);
  else if (this->rel_.is_local_section_symbol())
    addend = this->rel_.local_section_offset(addend);
  orel.put_r_addend(addend);
}

1213	  else if (this->rel_.is_symbolless())
(gdb) 
1214	    addend = this->rel_.symbol_value(addend);
(gdb) 
1217	  orel.put_r_addend(addend);
(gdb) p/x addend
$15 = 0x8000013f
(gdb) p/x this->addend_
$16 = 0x7fffffff
(gdb) 

Its sign changed.  This is OK for any other ELF32 relocations.
But R_X86_64_RELATIVE64 is an ELF32 relocation applied to a 64-bit
field.  Its addend can't change sign.