This is an archive of the discontinued LLVM Phabricator instance.

[ELF][MIPS] Always resolve MIPS GP-relative relocations to 'local' definitions
ClosedPublic

Authored by atanasyan on May 25 2016, 11:36 PM.

Details

Summary

In case of MIPS, GP-relative relocations always resolve to a definition in a regular input file, ignoring the one-definition rule. Such relocations are used to setup GP relative offsets in a function's prologue. So we, for example, should not attempt to create a dynamic relocation even if the target symbol is preemptible.

Fixes bug 27880.

Diff Detail

Repository
rL LLVM

Event Timeline

atanasyan updated this revision to Diff 58571.May 25 2016, 11:36 PM
atanasyan retitled this revision from to [ELF][MIPS] Always resolve MIPS GP-relative relocations to 'local' definitions.
atanasyan updated this object.
atanasyan added reviewers: rafael, ruiu.
atanasyan set the repository for this revision to rL LLVM.
atanasyan added a project: lld.
atanasyan added a subscriber: llvm-commits.
rafael added inline comments.May 26 2016, 6:11 AM
ELF/Relocations.cpp
244

From the description it looks like what you want is

static bool isPreemptible(const SymbolBody &B, RelExpr E) {

if (Config->EMachine == EM_MIPS &&  E == R_GOTREL)
  return false;
return Body.isPreemptible();

}

and use that in here instead of a plain Body.isPreemptible.

atanasyan updated this revision to Diff 58613.May 26 2016, 7:58 AM

Replace isForcedLinkTimeConstant by isPreemptible. It is better reflect the fact that we consider symbol as non-preemptible under some conditions.

rafael accepted this revision.May 27 2016, 7:05 AM
rafael edited edge metadata.

So, while this should work, it fairly undesirable that preemption depends on the relocation.

Any idea why gpword is used with a global? The comment in the MC parser implies it should be used with a local:

/ parseDirectiveGpWord
/ ::= .gpword local_sym

Also, llvm doesn't seem to print it for anything but jump tables.

So, long way of saying LGTM, but please add a fixme about dropping this once freebsd moves out of the prehistorical gcc.

This revision is now accepted and ready to land.May 27 2016, 7:05 AM

Any idea why gpword is used with a global?

It's my mistake. I select a wrong test case to show the problem (it was easier to copy-paste existing test code). A real case is R_MIPS_GPREL16. This relocation is used to setup GP offset in a function's prologue. That is why it should be always resolved locally. Here is an example. I am going to update the test case before commit.

  .text                                                                                                                                                                                                                                                     
  .global  entry                                                                                                                                                                                                                                            
entry:                                                                                                                                                                                                                                                      
  lui     $gp,%hi(%neg(%gp_rel(foo)))                                                                                                                                                                                                                       
  daddu   $gp,$gp,$t9                                                                                                                                                                                                                                       
  daddiu  $gp,$gp,%lo(%neg(%gp_rel(foo)))

R_MIPS_GPREL32 is for local symbols. But GNU linker does not show any error if R_MIPS_GPREL32's target is preemptible symbol. So I still think it is better to handle them uniformly too.

And thanks for review.

atanasyan updated this revision to Diff 58835.May 27 2016, 2:07 PM
atanasyan edited edge metadata.

Use stricter condition in the isPreemptible. Now we check on R_MIPS_GPREL16 relocation only because only this relocation can be against preemptible symbol and should be resolved locally. The side effect - isPreemptible routine becomes more complicated with a long comment describes handling 3-in-1 MIPS relocation packs.

Still LGTM?

This LGTM, but we should make sure that llvm instead produces something like

.global foo

foo:
.Lbar:

lui     $gp,%hi(%neg(%gp_rel(.Lbar)))
daddu   $gp,$gp,$t9
daddiu  $gp,$gp,%lo(%neg(%gp_rel(.Lbar))

so that we can on day remove this special case.

This revision was automatically updated to reflect the committed changes.