This is an archive of the discontinued LLVM Phabricator instance.

[Hexagon] R_HEX_GD_PLT_B22_PCREL cannot be relaxed.
ClosedPublic

Authored by sidneym on Mar 29 2020, 10:40 AM.

Details

Summary

This type of relocation cannot be relaxed. The branch referring to the symbol is redirected to __tls_get_addr.

Without this change lld could error out with ld.lld: error: relocation R_HEX_GD_PLT_B22_PCREL cannot refer to absolute symbol ... in some cases.

Diff Detail

Event Timeline

sidneym created this revision.Mar 29 2020, 10:40 AM
Herald added a project: Restricted Project. · View Herald Transcript

Calling a STT_TLS symbol (call a@GDPLT) seems strange. Tthe problem here is that a STT_TLS symbol is considered absolute by isAbsoluteValue. It is incorrect to reference a non-preemptible (due to -Bsymbolic) with an R_PC in PIC link.

I know that you had a previous change (D74443) which converted the target symbol to __tls_get_addr (not STT_TLS), which may be somehow related to this hack. Can you shall a bit more context why call a@GDPLT is used while a is STT_TLS?

lld/ELF/Relocations.cpp
1333

This can potentially break other targets.

1337–1340

Move the check here and check config->emachine == EM_HEXAGON

lld/test/ELF/hexagon-tls-gd-symbolic.s
8 ↗(On Diff #253435)

##

26 ↗(On Diff #253435)

section index is unneeded.

27 ↗(On Diff #253435)

Addresses are unneeded. Delete them

sidneym updated this revision to Diff 253617.Mar 30 2020, 10:00 AM

Update and add more context to the testcase.

call a@GDPLT is transformed to call tls_get_addr I added some more context to the testcase to show the sequence. I'm not sure just saying call a@GDPLT is just an alias for call tls_get_addr is 100% correct but that is basically how I think of it. Section 16.10 of the Hexagon ABI discusses this and the link is here:
http://lists.llvm.org/pipermail/llvm-dev/attachments/20190916/21516a52/attachment-0001.pdf

sidneym marked 4 inline comments as done.Mar 30 2020, 10:00 AM

OK, I kinda understand the scheme now. Suggest renaming and replacing the test:

% cat /tmp/c/hexagon-tls-gd-nonpreemptible.s
# REQUIRES: hexagon                                                                                                                                   
# RUN: llvm-mc -filetype=obj -triple=hexagon-unknown-elf %s -o %t.o        
# RUN: ld.lld -shared %t.o -o %t.so  
# RUN: llvm-readobj -r %t.so | FileCheck --check-prefix=RELOC %s
# RUN: llvm-objdump -d --no-show-raw-insn --print-imm-hex %t.so | FileCheck %s
                                                                           
## Prior to D77021 lld would error "relocation R_HEX_GD_PLT_B22_PCREL cannot refer to absolute symbol".
## A PC-relative relocation referencing a non-preemptible absolute symbol (due to STT_TLS) is not representable in -pie/-shared mode.
## For this case we will actually patch the symbol to the external __tls_get_addr which is preemptible.
                                                                           
.globl _start                                                              
.type _start, @function                                                    
                                                                           
# RELOC:      Section ({{.*}}) .rela.plt {  
# RELOC-NEXT:   R_HEX_JMP_SLOT - 0x0                                       
# RELOC-NEXT:   R_HEX_JMP_SLOT __tls_get_addr 0x0                  
# RELOC-NEXT: }                    
                                                                           
# CHECK:      { immext(#{{.*}})                                                                                                                       
# CHECK-NEXT:   r2 = add(pc,##{{.*}}) }                                    
# CHECK-NEXT: { immext(#{{.*}})                                                                                                                       
# CHECK-NEXT:   r0 = add(r2,##-{{.*}}) }                                                                                                              
# CHECK-NEXT: { call {{.*}} }                                                                                                                         
# CHECK-NEXT: { r0 = memw(r0+#0x0) } 
                                     
_start:                
  r2 = add(pc,##_GLOBAL_OFFSET_TABLE_@PCREL)
  r0 = add(r2,##a@GDGOT)
  call a@GDPLT
  r0 = memw(r0+#0)

## a is non-preemptible due to STV_HIDDEN visibility.
## We can achieve the same effect with -Bsymbolic.
.section        .tdata,"awT",@progbits
.globl  a
.hidden a
a:
.word 1

and updating the git description accordingly.

sidneym updated this revision to Diff 254296.Apr 1 2020, 2:16 PM

Use Fangrui's updated version of the testcase and rename it to hexagon-tls-gd-nonpreemptible.s. Appreciate the changes and added content it helps clarify the scenario being tested.

MaskRay accepted this revision.Apr 1 2020, 3:19 PM

LGTM. Please change the git description as well.

lld/ELF/Relocations.cpp
1339

We may patch (call a@GDPLT) to (call tls_get_addr), where tls_get_addr is non-preemptible. We can't relax the PLT relocation here.

lld/test/ELF/hexagon-tls-gd-nonpreemptible.s
2

Delete the empty line

This revision is now accepted and ready to land.Apr 1 2020, 3:19 PM
This revision was automatically updated to reflect the committed changes.