[PATCH] D30699: [ELF] - Stop producing broken output for R_386_GOT32X relocation.

George Rimar via llvm-commits llvm-commits at lists.llvm.org
Fri Mar 24 02:26:10 PDT 2017


>> ruiu added a comment.
>>
>> I spent a few hours to understand the situation. Here are my conclusions:
>>
>> 1. The expression to compute R_386_GOT32 value in the i386 psABI draft version 1.1 doesn't indeed make sense. It says that you need to use G+A (as opposed to G+A-GOT) >when the relocation is "[a]pplied on memory operand without base register when position-independent code is disabled". However, it is not doable because you are allowed to >use R_386_GOT32 anywhere and we cannot make an assumption that an R_386_GOT32 follows some certain limited set of instructions. I think this is a bug in the draft spec.
>>
>> 2. That being said, I believe what we are doing now for R_386_GOT32X is correct, and this patch will break it. When you compute G+A instead of G+A-GOT for an >R_386_GOT32X, you always need to rewrite instructions as well. If you don't rewrite instructions, you should always compute G+A-GOT (which is what we are currently doing.)
>>
>>
>> https://reviews.llvm.org/D30699
>
>"name at GOT" is a memory operand.  It is usually computed as "G + A" to
>get the GOT address.   If it is computed as G + A - GOT,
>
>op name at GOT, %reg
>
>will lead to random result since G + A - GOT is the GOT index, not address.

That is what my patch fixes for LLD.

>LEA is an exception, relocation in
>
>lea name at GOT, %reg
>
>should be computed as  G + A - GOT for the GOT index.   The motivation is
>to allow GOT access without base register when PIC is disabled.

That behavior is equal to what my patch do (because I do not change R_386_GOT32),
but that is not what gold head do currently, please see below. (gold do different because handles R_386_GOT32
in the same way as R_386_GOT32X)

>
>--
>H.J.

So if we have next code:
 movl ifunc at GOT, %eax
 movl foo at GOT, %eax
 lea ifunc at GOT, %eax
 lea foo at GOT, %eax

GAS generates next object with relocations:
   2: 8b 05 00 00 00 00    	mov    0x0,%eax (R_386_GOT32X)
   8: 8b 05 00 00 00 00    	mov    0x0,%eax (R_386_GOT32X)
   e: 8d 05 00 00 00 00    	lea    0x0,%eax (R_386_GOT32)
  14: 8d 05 00 00 00 00    	lea    0x0,%eax (R_386_GOT32)

GNU gold (GNU Binutils 2.28.51.20170215) 1.14 output is:
[ 5] .got PROGBITS        08049fec 000fec 000008 00  WA  0   0  4
gold head: 
 80480c2:	8b 05 ec 9f 04 08    	mov    0x8049fec,%eax (0x8049fec is an address in GOT, calculation is G + A)
 80480c8:	8d 05 c0 80 04 08    	lea    0x80480c0,%eax (mov was optimized to lea, 0x80480c0 is an address of ifunc).
 80480ce:	8d 05 ec 9f 04 08    	lea    0x8049fec,%eax (lea calculated as G + A, result is an address in GOT)
 80480d4:	8d 05 f0 9f 04 08    	lea    0x8049ff0,%eax (lea calculated as G + A, result is an address in GOT)

LLD without my patch currently generates:
   11002:	8b 05 f8 ff ff ff    	mov    0xfffffff8,%eax (result value here and below is an offset in GOT, calculation is G + A - GOT).
   11008:	8b 05 fc ff ff ff    	mov    0xfffffffc,%eax (we do not support mov->lea optimization yet, calculation is G + A - GOT)
   1100e:	8d 05 f8 ff ff ff    	lea    0xfffffff8,%eax (G + A - GOT)
   11014:	8d 05 fc ff ff ff    	lea    0xfffffffc,%eax (G + A - GOT)

LLD with my patch:
  [ 3] .got              PROGBITS        00012000 002000 000008 00  WA  0   0  4
   11002:	8b 05 00 20 01 00    	mov    0x12000,%eax (0x12000 is an address in GOT, calculation is G + A)
   11008:	8b 05 04 20 01 00    	mov    0x12004,%eax  (0x12004 is an address in GOT, calculation is G + A, we do not support mov->lea optimization yet)
   1100e:	8d 05 f8 ff ff ff    	lea    0xfffffff8,%eax (calculation is G + A - GOT)
   11014:	8d 05 fc ff ff ff    	lea    0xfffffffc,%eax (calculation is G + A - GOT)

So I think behavior with this patch is correct, and current LLD behavior is broken.

George.


More information about the llvm-commits mailing list