mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-06-20 01:50:24 +08:00
ELF32: don't silently truncate relocation addends
At least x86-64's x32 sub-mode and RISC-V's 32-bit mode calculate addends as 64-bit values, but store them in signed 32-bit fields when generating the file without encountering any earlier error. When the relocated field is a 64-bit one, the value resulting after processing the relocation record when linking (or the latest when loading) may thus be wrong due to the truncation. With the code change in place, one x32 testcase actually triggers the new diagnostic. That one case of too large a (negative) addend is being adjusted alongside the addition of a new testcase to actually trigger the new error. (Note that due to internal BFD behavior the relocation in .data doesn't get processed anymore after the errors in .text.) Note that in principle it is possible to express 64-bit relocations in ELF32, but this would require .rel relocations, i.e. with the addend stored in the 64-bit field being relocated. But I guess it would be a lot of effort for little gain to actually support this.
This commit is contained in:
@ -997,6 +997,19 @@ elf_write_relocs (bfd *abfd, asection *sec, void *data)
|
||||
return;
|
||||
}
|
||||
|
||||
#if defined(BFD64) && ARCH_SIZE == 32
|
||||
if (rela_hdr->sh_type == SHT_RELA
|
||||
&& ptr->howto->bitsize > 32
|
||||
&& ptr->addend - INT32_MIN > UINT32_MAX)
|
||||
{
|
||||
_bfd_error_handler (_("%pB: %pA+%"BFD_VMA_FMT"x: "
|
||||
"relocation addend %"BFD_VMA_FMT"x too large"),
|
||||
abfd, sec, ptr->address, ptr->addend);
|
||||
*failedp = true;
|
||||
bfd_set_error (bfd_error_bad_value);
|
||||
}
|
||||
#endif
|
||||
|
||||
src_rela.r_offset = ptr->address + addr_offset;
|
||||
src_rela.r_info = ELF_R_INFO (n, ptr->howto->type);
|
||||
src_rela.r_addend = ptr->addend;
|
||||
|
@ -38,6 +38,7 @@ if [expr ([istarget "i*86-*-*"] || [istarget "x86_64-*-*"]) && [gas_x32_check] &
|
||||
}
|
||||
|
||||
run_list_test "reloc64" "--defsym _bad_=1"
|
||||
run_list_test "reloc-2"
|
||||
|
||||
set ASFLAGS "$old_ASFLAGS"
|
||||
}
|
||||
|
4
gas/testsuite/gas/i386/ilp32/reloc-2.l
Normal file
4
gas/testsuite/gas/i386/ilp32/reloc-2.l
Normal file
@ -0,0 +1,4 @@
|
||||
.*: \.text\+2:.*addend.*too large.*
|
||||
.*: \.text\+b:.*addend.*too large.*
|
||||
.*: Assembler messages:
|
||||
.*: Fatal error: .*
|
7
gas/testsuite/gas/i386/ilp32/reloc-2.s
Normal file
7
gas/testsuite/gas/i386/ilp32/reloc-2.s
Normal file
@ -0,0 +1,7 @@
|
||||
.text
|
||||
_start:
|
||||
movabs $x+0x123456789, %rax
|
||||
movabs x+0x123456789, %eax
|
||||
|
||||
.data
|
||||
.quad x+0x123456789
|
@ -61,7 +61,8 @@ Disassembly of section \.text:
|
||||
.*[ ]+R_X86_64_TPOFF32[ ]+xtrn
|
||||
.*[ ]+R_X86_64_TPOFF32[ ]+xtrn
|
||||
.*[ ]+R_X86_64_TPOFF32[ ]+xtrn
|
||||
.*[ ]+R_X86_64_64[ ]+xtrn\+0x1
|
||||
.*[ ]+R_X86_64_64[ ]+xtrn\+0x7fffffff
|
||||
.*[ ]+R_X86_64_64[ ]+xtrn\-0x80000000
|
||||
Disassembly of section \.data:
|
||||
#...
|
||||
.*[ ]+R_X86_64_32[ ]+xtrn
|
||||
|
@ -51,17 +51,17 @@
|
||||
.*:175: Error: .*
|
||||
.*:176: Error: .*
|
||||
.*:177: Error: .*
|
||||
.*:189: Error: .*
|
||||
.*:192: Error: .* too large for field of 4 bytes at .*
|
||||
.*:190: Error: .*
|
||||
.*:193: Error: .* too large for field of 4 bytes at .*
|
||||
.*:194: Error: .* too large for field of 4 bytes at .*
|
||||
.*:195: Error: .* too large for field of 4 bytes at .*
|
||||
.*:196: Error: .* too large for field of 2 bytes at .*
|
||||
.*:196: Error: .* too large for field of 1 byte at .*
|
||||
.*:196: Error: .* too large for field of 4 bytes at .*
|
||||
.*:197: Error: .* too large for field of 2 bytes at .*
|
||||
.*:197: Error: .* too large for field of 1 byte at .*
|
||||
.*:200: Error: .* too large for field of 4 bytes at .*
|
||||
.*:201: Error: .* too large for field of 2 bytes at .*
|
||||
.*:198: Error: .* too large for field of 2 bytes at .*
|
||||
.*:198: Error: .* too large for field of 1 byte at .*
|
||||
.*:201: Error: .* too large for field of 4 bytes at .*
|
||||
.*:202: Error: .* too large for field of 2 bytes at .*
|
||||
.*:203: Error: .* too large for field of 1 byte at .*
|
||||
.*:203: Error: .* too large for field of 2 bytes at .*
|
||||
.*:204: Error: .* too large for field of 1 byte at .*
|
||||
.*:205: Error: .* too large for field of 1 byte at .*
|
||||
|
@ -178,7 +178,8 @@ bad .byte xtrn@tpoff
|
||||
|
||||
.text
|
||||
mov xtrn@tpoff (%rbx), %eax
|
||||
movabsq $xtrn - 4294967295, %rbp
|
||||
movabsq $xtrn + 0x7fffffff, %rbx
|
||||
movabsq $xtrn - 0x80000000, %rbp
|
||||
|
||||
.data
|
||||
.quad xtrn
|
||||
|
Reference in New Issue
Block a user