forked from OSchip/llvm-project
[MC][ELF] Emit a relocation if target is defined in the same section and is non-local
For a target symbol defined in the same section, currently we don't emit a relocation if VariantKind is VK_None (with few exceptions like RISC-V relaxation), while GNU as emits one. This causes program behavior differences with and without -ffunction-sections, and can break intended symbol interposition in a -shared link. ``` .globl foo foo: call foo # no relocation. On other targets, may be written as b foo, etc call bar # a relocation if bar is in another section (e.g. -ffunction-sections) call foo@plt # a relocation ``` Unify these cases by always emitting a relocation. If we ever want to optimize `call foo` in -shared links, we should emit a STB_LOCAL alias and call via the alias. ARM/thumb2-beq-fixup.s: we now emit a relocation to global_thumb_fn as GNU as does. X86/Inputs/align-branch-64-2.s: we now emit R_X86_64_PLT32 to foo as GNU does. ELF/relax.s: rewrite the test as target-in-same-section.s . We omitted relocations to `global` and now emit R_X86_64_PLT32. Note, GNU as does not emit a relocation for `jmp global` (maybe its own bug). Our new behavior is compatible except `jmp global`. Reviewed By: peter.smith Differential Revision: https://reviews.llvm.org/D72197
This commit is contained in:
parent
241f330d6b
commit
2bfee35cb8
|
@ -20,7 +20,7 @@ _start:
|
||||||
.long _GLOBAL_OFFSET_TABLE_ - .
|
.long _GLOBAL_OFFSET_TABLE_ - .
|
||||||
|
|
||||||
// CHECK: Name: _GLOBAL_OFFSET_TABLE_ (11)
|
// CHECK: Name: _GLOBAL_OFFSET_TABLE_ (11)
|
||||||
// CHECK-NEXT: Value: 0x30360
|
// CHECK-NEXT: Value:
|
||||||
// CHECK-NEXT: Size: 0
|
// CHECK-NEXT: Size: 0
|
||||||
// CHECK-NEXT: Binding: Local (0x0)
|
// CHECK-NEXT: Binding: Local (0x0)
|
||||||
// CHECK-NEXT: Type: None (0x0)
|
// CHECK-NEXT: Type: None (0x0)
|
||||||
|
|
|
@ -569,26 +569,6 @@ void ELFWriter::writeSymbol(SymbolTableWriter &Writer, uint32_t StringIndex,
|
||||||
IsReserved);
|
IsReserved);
|
||||||
}
|
}
|
||||||
|
|
||||||
// True if the assembler knows nothing about the final value of the symbol.
|
|
||||||
// This doesn't cover the comdat issues, since in those cases the assembler
|
|
||||||
// can at least know that all symbols in the section will move together.
|
|
||||||
static bool isWeak(const MCSymbolELF &Sym) {
|
|
||||||
if (Sym.getType() == ELF::STT_GNU_IFUNC)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
switch (Sym.getBinding()) {
|
|
||||||
default:
|
|
||||||
llvm_unreachable("Unknown binding");
|
|
||||||
case ELF::STB_LOCAL:
|
|
||||||
return false;
|
|
||||||
case ELF::STB_GLOBAL:
|
|
||||||
return false;
|
|
||||||
case ELF::STB_WEAK:
|
|
||||||
case ELF::STB_GNU_UNIQUE:
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ELFWriter::isInSymtab(const MCAsmLayout &Layout, const MCSymbolELF &Symbol,
|
bool ELFWriter::isInSymtab(const MCAsmLayout &Layout, const MCSymbolELF &Symbol,
|
||||||
bool Used, bool Renamed) {
|
bool Used, bool Renamed) {
|
||||||
if (Symbol.isVariable()) {
|
if (Symbol.isVariable()) {
|
||||||
|
@ -1534,7 +1514,7 @@ bool ELFObjectWriter::isSymbolRefDifferenceFullyResolvedImpl(
|
||||||
const auto &SymA = cast<MCSymbolELF>(SA);
|
const auto &SymA = cast<MCSymbolELF>(SA);
|
||||||
if (IsPCRel) {
|
if (IsPCRel) {
|
||||||
assert(!InSet);
|
assert(!InSet);
|
||||||
if (isWeak(SymA))
|
if (SymA.getBinding() != ELF::STB_LOCAL)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return MCObjectWriter::isSymbolRefDifferenceFullyResolvedImpl(Asm, SymA, FB,
|
return MCObjectWriter::isSymbolRefDifferenceFullyResolvedImpl(Asm, SymA, FB,
|
||||||
|
|
|
@ -18,4 +18,14 @@
|
||||||
@CHECK: Section {{.*}} .rel.text.cond {
|
@CHECK: Section {{.*}} .rel.text.cond {
|
||||||
@CHECK: 0x0 R_ARM_THM_JUMP8
|
@CHECK: 0x0 R_ARM_THM_JUMP8
|
||||||
@CHECK: }
|
@CHECK: }
|
||||||
|
|
||||||
|
.section .text.insection
|
||||||
|
.globl global
|
||||||
|
local:
|
||||||
|
global:
|
||||||
|
b local
|
||||||
|
b global
|
||||||
|
|
||||||
|
@CHECK: Section {{.*}} .rel.text.insection {
|
||||||
|
@CHECK-NEXT: 0x2 R_ARM_THM_JUMP11 global 0x0
|
||||||
|
@CHECK-NEXT: }
|
||||||
|
|
|
@ -36,4 +36,5 @@ global_thumb_fn:
|
||||||
@ CHECK: Section (3) .rel.text
|
@ CHECK: Section (3) .rel.text
|
||||||
@ CHECK-NEXT: 0x0 R_ARM_THM_JUMP19 internal_arm_fn 0x0
|
@ CHECK-NEXT: 0x0 R_ARM_THM_JUMP19 internal_arm_fn 0x0
|
||||||
@ CHECK-NEXT: 0x4 R_ARM_THM_JUMP19 global_arm_fn 0x0
|
@ CHECK-NEXT: 0x4 R_ARM_THM_JUMP19 global_arm_fn 0x0
|
||||||
|
@ CHECK-NEXT: 0x8 R_ARM_THM_JUMP19 global_thumb_fn 0x0
|
||||||
@ CHECK-NEXT: }
|
@ CHECK-NEXT: }
|
||||||
|
|
|
@ -1,33 +0,0 @@
|
||||||
// RUN: llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu %s -o - | llvm-readobj -S --sd --symbols | FileCheck %s
|
|
||||||
|
|
||||||
// Test that we do not relax these.
|
|
||||||
|
|
||||||
bar:
|
|
||||||
.globl foo
|
|
||||||
foo:
|
|
||||||
.set zed,foo
|
|
||||||
|
|
||||||
jmp bar
|
|
||||||
jmp foo
|
|
||||||
jmp zed
|
|
||||||
|
|
||||||
// CHECK: Section {
|
|
||||||
// CHECK: Name: .text
|
|
||||||
// CHECK-NEXT: Type: SHT_PROGBITS
|
|
||||||
// CHECK-NEXT: Flags [
|
|
||||||
// CHECK-NEXT: SHF_ALLOC
|
|
||||||
// CHECK-NEXT: SHF_EXECINSTR
|
|
||||||
// CHECK-NEXT: ]
|
|
||||||
// CHECK-NEXT: Address: 0x0
|
|
||||||
// CHECK-NEXT: Offset: 0x40
|
|
||||||
// CHECK-NEXT: Size: 6
|
|
||||||
// CHECK-NEXT: Link: 0
|
|
||||||
// CHECK-NEXT: Info: 0
|
|
||||||
// CHECK-NEXT: AddressAlignment: 4
|
|
||||||
// CHECK-NEXT: EntrySize: 0
|
|
||||||
// CHECK-NEXT: SectionData (
|
|
||||||
// CHECK-NEXT: 0000: EBFEEBFC EBFA
|
|
||||||
// CHECK-NEXT: )
|
|
||||||
// CHECK-NEXT: }
|
|
||||||
// CHECK: Symbol {
|
|
||||||
// CHECK: Name: foo
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
## For a target defined in the same section, create a relocation if the
|
||||||
|
## symbol is not local, otherwise resolve the fixup statically.
|
||||||
|
# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t
|
||||||
|
# RUN: llvm-readobj -r %t | FileCheck --check-prefix=RELOC %s
|
||||||
|
# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s
|
||||||
|
|
||||||
|
# RELOC: .rela.text {
|
||||||
|
# RELOC-NEXT: 0x5 R_X86_64_PLT32 global 0xFFFFFFFFFFFFFFFC
|
||||||
|
# RELOC-NEXT: 0xA R_X86_64_PLT32 weak 0xFFFFFFFFFFFFFFFC
|
||||||
|
# RELOC-NEXT: 0x19 R_X86_64_PLT32 global 0xFFFFFFFFFFFFFFFC
|
||||||
|
# RELOC-NEXT: 0x1E R_X86_64_PLT32 weak 0xFFFFFFFFFFFFFFFC
|
||||||
|
# RELOC-NEXT: }
|
||||||
|
|
||||||
|
# CHECK: 0: jmp
|
||||||
|
# CHECK-NEXT: 2: jmp
|
||||||
|
# CHECK-NEXT: 4: jmp
|
||||||
|
# CHECK-NEXT: 9: jmp
|
||||||
|
# CHECK-NEXT: e: callq
|
||||||
|
# CHECK-NEXT: 13: callq
|
||||||
|
# CHECK-NEXT: 18: callq
|
||||||
|
# CHECK-NEXT: 1d: callq
|
||||||
|
# CHECK-NEXT: 22: retq
|
||||||
|
|
||||||
|
.globl global
|
||||||
|
.weak weak
|
||||||
|
global:
|
||||||
|
weak:
|
||||||
|
local:
|
||||||
|
.set var,global
|
||||||
|
jmp var
|
||||||
|
jmp local
|
||||||
|
jmp global
|
||||||
|
jmp weak
|
||||||
|
|
||||||
|
call var
|
||||||
|
call local
|
||||||
|
call global
|
||||||
|
call weak
|
||||||
|
ret
|
|
@ -12,6 +12,6 @@
|
||||||
# CHECK-NEXT: 3e: ff d0 callq *%rax
|
# CHECK-NEXT: 3e: ff d0 callq *%rax
|
||||||
# CHECK-COUNT-3: : 64 89 04 25 01 00 00 00 movl %eax, %fs:1
|
# CHECK-COUNT-3: : 64 89 04 25 01 00 00 00 movl %eax, %fs:1
|
||||||
# CHECK-NEXT: 58: 55 pushq %rbp
|
# CHECK-NEXT: 58: 55 pushq %rbp
|
||||||
# CHECK-NEXT: 59: e8 a2 ff ff ff callq {{.*}}
|
# CHECK-NEXT: 59: e8 00 00 00 00 callq {{.*}}
|
||||||
# CHECK-COUNT-4: : 64 89 04 25 01 00 00 00 movl %eax, %fs:1
|
# CHECK-COUNT-4: : 64 89 04 25 01 00 00 00 movl %eax, %fs:1
|
||||||
# CHECK: 7e: ff 14 25 00 00 00 00 callq *0
|
# CHECK: 7e: ff 14 25 00 00 00 00 callq *0
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
# CHECK-NEXT: 3c: ff d0 callq *%rax
|
# CHECK-NEXT: 3c: ff d0 callq *%rax
|
||||||
# CHECK-COUNT-3: : 64 89 04 25 01 00 00 00 movl %eax, %fs:1
|
# CHECK-COUNT-3: : 64 89 04 25 01 00 00 00 movl %eax, %fs:1
|
||||||
# CHECK: 56: 55 pushq %rbp
|
# CHECK: 56: 55 pushq %rbp
|
||||||
# CHECK-NEXT: 57: e8 a4 ff ff ff callq {{.*}}
|
# CHECK-NEXT: 57: e8 00 00 00 00 callq {{.*}}
|
||||||
# CHECK-COUNT-4: : 64 89 04 25 01 00 00 00 movl %eax, %fs:1
|
# CHECK-COUNT-4: : 64 89 04 25 01 00 00 00 movl %eax, %fs:1
|
||||||
# CHECK-COUNT-4: : 90 nop
|
# CHECK-COUNT-4: : 90 nop
|
||||||
# CHECK: 80: ff 14 25 00 00 00 00 callq *0
|
# CHECK: 80: ff 14 25 00 00 00 00 callq *0
|
||||||
|
|
|
@ -14,6 +14,6 @@
|
||||||
# CHECK-COUNT-3: : 64 89 04 25 01 00 00 00 movl %eax, %fs:1
|
# CHECK-COUNT-3: : 64 89 04 25 01 00 00 00 movl %eax, %fs:1
|
||||||
# CHECK: 5a: 55 pushq %rbp
|
# CHECK: 5a: 55 pushq %rbp
|
||||||
# CHECK-COUNT-5: : 90 nop
|
# CHECK-COUNT-5: : 90 nop
|
||||||
# CHECK: 60: e8 9b ff ff ff callq {{.*}}
|
# CHECK: 60: e8 00 00 00 00 callq {{.*}}
|
||||||
# CHECK-COUNT-4: : 64 89 04 25 01 00 00 00 movl %eax, %fs:1
|
# CHECK-COUNT-4: : 64 89 04 25 01 00 00 00 movl %eax, %fs:1
|
||||||
# CHECK: 85: ff 14 25 00 00 00 00 callq *0
|
# CHECK: 85: ff 14 25 00 00 00 00 callq *0
|
||||||
|
|
Loading…
Reference in New Issue