optimization/10877: [3.3/3.4 regression] miscompilation with -O3 -fPIC on x86

Christian Ehrhardt ehrhardt@mathematik.uni-ulm.de
Wed May 21 13:16:00 GMT 2003


[ Added Eric to cc because his patch might have triggered this gas bug. ]

On Tue, May 20, 2003 at 12:05:35PM -0500, Wolfgang Bangerth wrote:
> > Feeding this assembler file into gcc 3.2 on an Intel box works for me
> > and the program doesn't crash! This might mean that we have an
> > assembler/binutils problem here.
> 
> Whereas if I do the same, it crashes. So you seem to have a point :-)

This is definitely a gas Bug! The problem is the following instruction:

	addl    $_GLOBAL_OFFSET_TABLE_, %eax

This tells the assembler that we want the difference between the adress
of this addl instruction and the start of the global offset table to be
added to %eax. When translating this request into relocation records an
R_386_GOTPC relocation is used.
However, this relocation calculates the difference between the place where
the relocation takes place and the start of the global offset table.
Hence the assembler must add an addend to fix up the difference between
the address of the addl instruction and the address of its immediate
operand (the latter is the place of the relocation).

Now in the %eax case gas emmits the 0x05 opcode for addl imm32,%eax
with a length of 1 byte. If the register isn't %eax the assembler
has to use the longer 0x81 0xc3 opcode. Both opcodes are followed by
the immediate 32bit Operand.

I.e. if %eax is used the addend for the R_386_GOTPC relocation must be 1
but for all other registers it must be 2 due to the different length of
the opcode. This is what some gas versions seem to get wrong.

So what should we do with this report? Do we want to work around
this bug in gcc or should we close it and tell people to upgrade
binutils. The bug is fixed at least since 2.12.90.0.15 20020717 (SuSE).

   regards   Christian

-- 
THAT'S ALL FOLKS!



More information about the Gcc-bugs mailing list