This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
Re: Commit: PR 22823: Fix gcc 8 compile time warnings
- From: "Maciej W. Rozycki" <macro at mips dot com>
- To: Nick Clifton <nickc at redhat dot com>
- Cc: <binutils at sourceware dot org>
- Date: Wed, 14 Feb 2018 02:59:34 +0000
- Subject: Re: Commit: PR 22823: Fix gcc 8 compile time warnings
- Authentication-results: sourceware.org; auth=none
- References: <8760716n3w.fsf@redhat.com>
Hi Nick,
> I am applying the attached patch to fix the compile time warnings that
> are generated when compiling the binutils with gcc v8.0.1. Almost all
> of them were about conflicts in the casts of function pointers to
> dummy functions. To solve this I chose to create a set of extra dummy
> functions which accept a variable number of arguments. Thus
> satisfying the compiler and allowing the build to finish.
Unfortunately this has broken LD severely, in a host rather than target
dependent manner I believe. I can see it with the `x86_64-linux' host and
the `mips-linux' target as numerous segfaults throughout the LD test
suite.
The thing is the new `bfd_false_any' function is a variable-argument one
and expects the argument count in $rax, as per the x86-64 psABI[1]. This
is how compiled code looks like:
Dump of assembler code for function bfd_false_any:
0x0000000000455119 <bfd_false_any+0>: push %rbp
0x000000000045511a <bfd_false_any+1>: mov %rsp,%rbp
0x000000000045511d <bfd_false_any+4>: sub $0xc0,%rsp
0x0000000000455124 <bfd_false_any+11>: mov %rsi,-0xa8(%rbp)
0x000000000045512b <bfd_false_any+18>: mov %rdx,-0xa0(%rbp)
0x0000000000455132 <bfd_false_any+25>: mov %rcx,-0x98(%rbp)
0x0000000000455139 <bfd_false_any+32>: mov %r8,-0x90(%rbp)
0x0000000000455140 <bfd_false_any+39>: mov %r9,-0x88(%rbp)
0x0000000000455147 <bfd_false_any+46>: movzbl %al,%eax
0x000000000045514a <bfd_false_any+49>: mov %rax,-0xc0(%rbp)
0x0000000000455151 <bfd_false_any+56>: mov -0xc0(%rbp),%rdx
0x0000000000455158 <bfd_false_any+63>: lea 0x0(,%rdx,4),%rax
0x0000000000455160 <bfd_false_any+71>: movq $0x45519f,-0xc0(%rbp)
0x000000000045516b <bfd_false_any+82>: sub %rax,-0xc0(%rbp)
0x0000000000455172 <bfd_false_any+89>: lea -0x1(%rbp),%rax
0x0000000000455176 <bfd_false_any+93>: mov -0xc0(%rbp),%rdx
0x000000000045517d <bfd_false_any+100>: jmpq *%rdx
0x000000000045517f <bfd_false_any+102>: movaps %xmm7,-0xf(%rax)
0x0000000000455183 <bfd_false_any+106>: movaps %xmm6,-0x1f(%rax)
0x0000000000455187 <bfd_false_any+110>: movaps %xmm5,-0x2f(%rax)
0x000000000045518b <bfd_false_any+114>: movaps %xmm4,-0x3f(%rax)
0x000000000045518f <bfd_false_any+118>: movaps %xmm3,-0x4f(%rax)
0x0000000000455193 <bfd_false_any+122>: movaps %xmm2,-0x5f(%rax)
0x0000000000455197 <bfd_false_any+126>: movaps %xmm1,-0x6f(%rax)
0x000000000045519b <bfd_false_any+130>: movaps %xmm0,-0x7f(%rax)
0x000000000045519f <bfd_false_any+134>: mov %rdi,-0xb8(%rbp)
0x00000000004551a6 <bfd_false_any+141>: mov $0x5,%edi
0x00000000004551ab <bfd_false_any+146>: callq 0x44eda4 <bfd_set_error>
0x00000000004551b0 <bfd_false_any+151>: mov $0x0,%eax
0x00000000004551b5 <bfd_false_any+156>: leaveq
0x00000000004551b6 <bfd_false_any+157>: retq
End of assembler dump.
This code breaks when called as the handler for
`bed->elf_backend_allow_non_load_phdr' from elf.c:6141 in
`assign_file_positions_except_relocs'.
The incoming value of $rax is 0x91d920, an outcome from earlier
operations and not set up for the call to `bfd_false_any'. This gets
truncated to 0x20 at 0x455147, multiplied by 4 at 0x455158 and subtracted
from 0x45519f at 0x45516b, to calculate which of the 8 MOVAPS instructions
ending at 0x45519f to jump to at 0x45517d. As 0x20 is above 8, this
calculation causes an overrun and as a result the jump is made to 0x45511f
to what is now interpreted as this instruction:
0x45511f <bfd_false_any+6>: in (%dx),%al
which then segfaults. This happens at `-O0'; perhaps the optimiser hides
the problem with optimisation enabled.
For some host psABIs I suppose initialising a fixed-argument function
pointer with a variable-argument function reference and then using the
pointer to make a call is going to work, but this is UB AFAIK as per the C
language standard, so I suggest that you revert your change and look for a
better alternative, as the cure seems worse than the disease.
NB I don't know where the idea of complaining about extraneous function
arguments has come from for GCC 8 (except maybe for `-pedantic'), as this
property of the C vs Pascal function calling convention has been relied on
since forever.
References:
[1] "System V Application Binary Interface AMD64 Architecture Processor
Supplement", Draft Version 0.99.6, July 2, 2012, Section 3.5.7
"Variable Argument Lists", p. 50
Maciej