diff --git a/llvm/lib/MC/MCAssembler.cpp b/llvm/lib/MC/MCAssembler.cpp --- a/llvm/lib/MC/MCAssembler.cpp +++ b/llvm/lib/MC/MCAssembler.cpp @@ -216,6 +216,21 @@ return true; } } + if (const MCSymbolRefExpr *RefA = Target.getSymA()) { + // If SymA is equated to an expression with an undefined symbol, GNU as + // converts the fixup to be against the target symbol. We only support a + // simple form `alias = aliasee` (MCSymbolRefExpr). + const auto &SymA = RefA->getSymbol(); + if (SymA.isVariable()) { + if (const auto *SRE = dyn_cast(SymA.getVariableValue())) + if (SRE->getSymbol().isUndefined() && + SRE->getKind() != MCSymbolRefExpr::VK_WEAKREF) { + Target = MCValue::get( + MCSymbolRefExpr::create(&SRE->getSymbol(), RefA->getKind(), Ctx), + Target.getSymB(), Target.getConstant(), Target.getRefKind()); + } + } + } assert(getBackendPtr() && "Expected assembler backend"); bool IsTarget = getBackendPtr()->getFixupKindInfo(Fixup.getKind()).Flags & 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,38 @@ +# 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. +# 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 + +## NOTE: GNU as redirects memcpy_plus_1. +# CHECK: callq {{.*}} +# CHECK-NEXT: R_X86_64_PLT32 memcpy_plus_1 +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 + +.data +.byte 0 +.globl data +data: + +## Redirected symbols do not have a symbol table entry. +# SYM: NOTYPE LOCAL DEFAULT UND +# SYM-NEXT: NOTYPE GLOBAL DEFAULT UND __GI_memcpy +# SYM-NEXT: NOTYPE GLOBAL DEFAULT 4 data +# SYM-NEXT: NOTYPE GLOBAL DEFAULT 4 data_alias +# SYM-NEXT: NOTYPE GLOBAL DEFAULT UND memcpy_plus_1 +# SYM-NOT: {{.}}