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
@@ -802,13 +802,30 @@
   case SymbolRef: {
     const MCSymbolRefExpr *SRE = cast<MCSymbolRefExpr>(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)) {
+        if (Kind != MCSymbolRefExpr::VK_None) {
+          if (Res.isAbsolute()) {
+            Res = MCValue::get(SRE, nullptr, 0);
+            return true;
+          }
+          // If the reference has a variant kind, we can only handle expressions
+          // which evaluate exactly to a single unadorned symbol. Attach the
+          // original VariantKind to SymA of the result.
+          if (Res.getRefKind() != MCSymbolRefExpr::VK_None || !Res.getSymA() ||
+              Res.getSymB() || Res.getConstant())
+            return false;
+          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
@@ -9,5 +9,6 @@
 	bx lr
 	.fnend
 
+@@ Regression test: MC does not crash due to the absolute __aeabi_unwind_cpp_pr0.
+@@ GNU as and MC currently emit a R_ARM_NONE for this invalid usage.
 @ CHECK: R_ARM_NONE __aeabi_unwind_cpp_pr0
-
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,55 @@
+# 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
+
+# RUN: not llvm-mc -filetype=obj -triple x86_64 --defsym ERR=1 %s 2>&1 | FileCheck %s --check-prefix=ERR
+
+## 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:      movq (%rip), %rax
+# CHECK-NEXT:   R_X86_64_REX_GOTPCRELX  abs-0x4
+movq abs@GOTPCREL(%rip), %rax
+abs = 42
+
+# 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:
+
+.ifdef ERR
+.text
+## Note, GNU as emits a relocation for this erroneous fixup.
+# ERR: {{.*}}.s:[[#@LINE+2]]:1: error: expected relocatable expression
+memcpy_plus_1 = __GI_memcpy+1
+call memcpy_plus_1@PLT
+.endif
+
+## Redirected symbols do not have a symbol table entry.
+# SYM:      NOTYPE  LOCAL  DEFAULT UND
+# SYM-NEXT: NOTYPE  LOCAL  DEFAULT ABS abs
+# 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
@@ -32,10 +32,7 @@
         movabsq	$baz@TPOFF, %rax
 	.word   foo-bar
 	.byte   foo-bar
-
-        # this should probably be an error...
-	zed = foo +2
-	call zed@PLT
+	call foo
 
         leaq    -1+foo(%rip), %r11
 
@@ -94,7 +91,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 0xFFFFFFFFFFFFFFFC
 // 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