diff --git a/llvm/lib/MC/MCExpr.cpp b/llvm/lib/MC/MCExpr.cpp --- a/llvm/lib/MC/MCExpr.cpp +++ b/llvm/lib/MC/MCExpr.cpp @@ -800,13 +800,21 @@ case SymbolRef: { const MCSymbolRefExpr *SRE = cast(this); const MCSymbol &Sym = SRE->getSymbol(); + const auto Kind = SRE->getKind(); // Evaluate recursively if this is a variable. - if (Sym.isVariable() && SRE->getKind() == MCSymbolRefExpr::VK_None && + if (Sym.isVariable() && (Kind == MCSymbolRefExpr::VK_None || Layout) && canExpand(Sym, InSet)) { bool IsMachO = SRE->hasSubsectionsViaSymbols(); if (Sym.getVariableValue()->evaluateAsRelocatableImpl( Res, Asm, Layout, Fixup, Addrs, InSet || IsMachO)) { + // Attach the original VariantKind to SymA of the result. + if (Layout && Res.getSymA()) { + Res = + MCValue::get(MCSymbolRefExpr::create(&Res.getSymA()->getSymbol(), + Kind, Asm->getContext()), + Res.getSymB(), Res.getConstant(), Res.getRefKind()); + } if (!IsMachO) return true; diff --git a/llvm/test/MC/ARM/ehabi-personality-abs.s b/llvm/test/MC/ARM/ehabi-personality-abs.s --- a/llvm/test/MC/ARM/ehabi-personality-abs.s +++ b/llvm/test/MC/ARM/ehabi-personality-abs.s @@ -1,4 +1,4 @@ -@ RUN: llvm-mc -triple armv7-linux -filetype obj -o - %s | llvm-objdump --triple=armv7 -D -r - | FileCheck %s +@ RUN: llvm-mc -triple armv7-linux -filetype obj -o - %s | llvm-readobj -r - | FileCheck %s .text @@ -9,5 +9,7 @@ bx lr .fnend -@ CHECK: R_ARM_NONE __aeabi_unwind_cpp_pr0 - +@@ GNU as also emits a R_ARM_NONE, which is insignificant. +@ CHECK: Section {{.*}} .rel.ARM.exidx { +@ CHECK-NEXT: 0x0 R_ARM_PREL31 .text 0x0 +@ CHECK-NEXT: } diff --git a/llvm/test/MC/ELF/relocation-alias.s b/llvm/test/MC/ELF/relocation-alias.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/ELF/relocation-alias.s @@ -0,0 +1,44 @@ +# RUN: llvm-mc -filetype=obj -triple x86_64 %s -o %t +# RUN: llvm-objdump -dr %t | FileCheck %s +# RUN: llvm-readelf -s %t | FileCheck %s --check-prefix=SYM + +## If a fixup symbol is equated to an undefined symbol, convert the fixup +## to be against the target symbol, even if there is a variant (@PLT). +# CHECK: callq {{.*}} +# CHECK-NEXT: R_X86_64_PLT32 __GI_memcpy-0x4 +# CHECK: movabsq $0, %rax +# CHECK-NEXT: R_X86_64_64 __GI_memcpy+0x2 +memcpy = __GI_memcpy +call memcpy@PLT +movabsq $memcpy+2, %rax + +# CHECK: callq {{.*}} +# CHECK-NEXT: R_X86_64_PLT32 __GI_memcpy-0x3 +memcpy_plus_1 = __GI_memcpy+1 +call memcpy_plus_1@PLT + +# CHECK: movabsq $0, %rbx +# CHECK-NEXT: R_X86_64_64 data_alias +.globl data_alias +.set data_alias, data +movabsq $data_alias, %rbx + +## A local alias to a defined symbol still references a section symbol. +# CHECK: movabsq $0, %rbx +# CHECK-NEXT: R_X86_64_64 .data+0x1 +.set data_alias_l, data +movabsq $data_alias_l, %rbx + +.data +.byte 0 +.globl data +data: + +## Redirected symbols do not have a symbol table entry. +# SYM: NOTYPE LOCAL DEFAULT UND +# SYM-NEXT: NOTYPE LOCAL DEFAULT 4 data_alias_l +# SYM-NEXT: SECTION LOCAL DEFAULT 4 .data +# SYM-NEXT: NOTYPE GLOBAL DEFAULT UND __GI_memcpy +# SYM-NEXT: NOTYPE GLOBAL DEFAULT 4 data +# SYM-NEXT: NOTYPE GLOBAL DEFAULT 4 data_alias +# SYM-NOT: {{.}} diff --git a/llvm/test/MC/ELF/relocation.s b/llvm/test/MC/ELF/relocation.s --- a/llvm/test/MC/ELF/relocation.s +++ b/llvm/test/MC/ELF/relocation.s @@ -94,7 +94,7 @@ // CHECK-NEXT: 0x85 R_X86_64_TPOFF64 baz 0x0 // CHECK-NEXT: 0x8D R_X86_64_PC16 foo 0x8D // CHECK-NEXT: 0x8F R_X86_64_PC8 foo 0x8F -// CHECK-NEXT: 0x91 R_X86_64_PLT32 zed 0xFFFFFFFFFFFFFFFC +// CHECK-NEXT: 0x91 R_X86_64_PLT32 foo 0xFFFFFFFFFFFFFFFE // CHECK-NEXT: 0x98 R_X86_64_PC32 foo 0xFFFFFFFFFFFFFFFB // CHECK-NEXT: 0x9F R_X86_64_GOTPC32 _GLOBAL_OFFSET_TABLE_ 0x3 // CHECK-NEXT: 0xA6 R_X86_64_GOTPC32 _GLOBAL_OFFSET_TABLE_ 0xFFFFFFFFFFFFFFFC