[PATCH] D19115: [ELF][MIPS] Make R_MIPS_LO16 a relative relocation if it references _gp_disp symbol
Rafael Espíndola via llvm-commits
llvm-commits at lists.llvm.org
Thu Apr 14 12:03:28 PDT 2016
LGTM, thanks.
On 14 April 2016 at 11:03, Simon Atanasyan <simon at atanasyan.com> wrote:
> atanasyan created this revision.
> atanasyan added a reviewer: rafael.
> atanasyan added a subscriber: llvm-commits.
> atanasyan set the repository for this revision to rL LLVM.
> atanasyan added a project: lld.
> Herald added a subscriber: sdardis.
>
> The _gp_disp symbol designates offset between start of function and 'gp' pointer into GOT. The following code is a typical MIPS function preamble used to setup $gp register:
> ```
> lui $gp, %hi(_gp_disp)
> addi $gp, $gp, %lo(_gp_disp)
> ```
> To calculate R_MIPS_HI16 / R_MIPS_LO16 relocations results we use the following formulas:
> ```
> %hi(_gp - P + A)
> %lo(_gp - P + A + 4),
> ```
> where _gp is a value of _gp symbol, A is addend, and P current address.
>
> The R_MIPS_LO16 relocation references _gp_disp symbol is always the second instruction. That is why we need four byte adjustments. The patch assigns R_PC type for R_MIPS_LO16 relocation and adjusts its addend by 4. That fix R_MIPS_LO16 calculation.
>
> For details see p. 4-19 at ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
>
> Repository:
> rL LLVM
>
> http://reviews.llvm.org/D19115
>
> Files:
> ELF/Target.cpp
> ELF/Writer.cpp
> test/ELF/mips-hilo-gp-disp.s
>
> Index: test/ELF/mips-hilo-gp-disp.s
> ===================================================================
> --- test/ELF/mips-hilo-gp-disp.s
> +++ test/ELF/mips-hilo-gp-disp.s
> @@ -16,27 +16,40 @@
> lui $t0,%hi(_gp_disp)
> addi $t0,$t0,%lo(_gp_disp)
> lw $v0,%call16(_foo)($gp)
> +bar:
> + lui $t0,%hi(_gp_disp)
> + addi $t0,$t0,%lo(_gp_disp)
>
> # EXE: Disassembly of section .text:
> # EXE-NEXT: __start:
> # EXE-NEXT: 20000: 3c 08 00 01 lui $8, 1
> # ^-- %hi(0x37ff0-0x20000)
> # EXE-NEXT: 20004: 21 08 7f f0 addi $8, $8, 32752
> # ^-- %lo(0x37ff0-0x20004+4)
> +# EXE: bar:
> +# EXE-NEXT: 2000c: 3c 08 00 01 lui $8, 1
> +# ^-- %hi(0x37ff0-0x2000c)
> +# EXE-NEXT: 20010: 21 08 7f e4 addi $8, $8, 32740
> +# ^-- %lo(0x37ff0-0x20010+4)
>
> # EXE: SYMBOL TABLE:
> +# EXE: 0002000c .text 00000000 bar
> # EXE: 00037ff0 .got 00000000 .hidden _gp
> # EXE: 00020000 .text 00000000 __start
> -# EXE: 00020010 .text 00000000 _foo
>
> # SO: Disassembly of section .text:
> # SO-NEXT: __start:
> # SO-NEXT: 10000: 3c 08 00 01 lui $8, 1
> # ^-- %hi(0x27ff0-0x10000)
> # SO-NEXT: 10004: 21 08 7f f0 addi $8, $8, 32752
> # ^-- %lo(0x27ff0-0x10004+4)
> +# SO: bar:
> +# SO-NEXT: 1000c: 3c 08 00 01 lui $8, 1
> +# ^-- %hi(0x27ff0-0x1000c)
> +# SO-NEXT: 10010: 21 08 7f e4 addi $8, $8, 32740
> +# ^-- %lo(0x27ff0-0x10010+4)
>
> # SO: SYMBOL TABLE:
> +# SO: 0001000c .text 00000000 bar
> # SO: 00027ff0 .got 00000000 .hidden _gp
> # SO: 00010000 .text 00000000 __start
> -# SO: 00010010 .text 00000000 _foo
> Index: ELF/Writer.cpp
> ===================================================================
> --- ELF/Writer.cpp
> +++ ELF/Writer.cpp
> @@ -468,8 +468,16 @@
> const uint8_t *BufLoc = Buf + RI.r_offset;
> if (!RelTy::IsRela)
> Addend += Target->getImplicitAddend(BufLoc, Type);
> - if (Config->EMachine == EM_MIPS)
> + if (Config->EMachine == EM_MIPS) {
> Addend += findMipsPairedAddend<ELFT>(Buf, BufLoc, Body, &RI, E);
> + if (Type == R_MIPS_LO16 && Expr == R_PC)
> + // R_MIPS_LO16 expression has R_PC type iif the target is _gp_disp
> + // symbol. In that case we should use the following formula for
> + // calculation "AHL + GP – P + 4". Let's add 4 right here.
> + // For details see p. 4-19 at
> + // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
> + Addend += 4;
> + }
>
> bool Preemptible = Body.isPreemptible();
> if (unsigned Processed =
> Index: ELF/Target.cpp
> ===================================================================
> --- ELF/Target.cpp
> +++ ELF/Target.cpp
> @@ -1589,6 +1589,7 @@
> default:
> return R_ABS;
> case R_MIPS_HI16:
> + case R_MIPS_LO16:
> // MIPS _gp_disp designates offset between start of function and 'gp'
> // pointer into GOT. __gnu_local_gp is equal to the current value of
> // the 'gp'. Therefore any relocations against them do not require
>
>
More information about the llvm-commits
mailing list