diff options
author | Rafael Espindola <rafael.espindola@gmail.com> | 2014-03-20 02:12:01 +0000 |
---|---|---|
committer | Rafael Espindola <rafael.espindola@gmail.com> | 2014-03-20 02:12:01 +0000 |
commit | 7fadc0ea7df49f4fef7da3797ea382d9486cc259 (patch) | |
tree | a240de0de7267b634fd4b36e1e7673f661941f53 /llvm/lib/MC/MCExpr.cpp | |
parent | 05c152b5d134a878ae8781d6fc3b8619f387c9de (diff) | |
download | bcm5719-llvm-7fadc0ea7df49f4fef7da3797ea382d9486cc259.tar.gz bcm5719-llvm-7fadc0ea7df49f4fef7da3797ea382d9486cc259.zip |
Look through variables when computing relocations.
Given
bar = foo + 4
.long bar
MC would eat the 4. GNU as includes it in the relocation. The rule seems to be
that a variable that defines a symbol is used in the relocation and one that
does not define a symbol is evaluated and the result included in the relocation.
Fixing this unfortunately required some other changes:
* Since the variable is now evaluated, it would prevent the ELF writer from
noticing the weakref marker the elf streamer uses. This patch then replaces
that with a VariantKind in MCSymbolRefExpr.
* Using VariantKind then requires us to look past other VariantKind to see
.weakref bar,foo
call bar@PLT
doing this also fixes
zed = foo +2
call zed@PLT
so that is a good thing.
* Looking past VariantKind means that the relocation selection has to use
the fixup instead of the target.
This is a reboot of the previous fixes for MC. I will watch the sanitizer
buildbot and wait for a build before adding back the previous fixes.
llvm-svn: 204294
Diffstat (limited to 'llvm/lib/MC/MCExpr.cpp')
-rw-r--r-- | llvm/lib/MC/MCExpr.cpp | 33 |
1 files changed, 24 insertions, 9 deletions
diff --git a/llvm/lib/MC/MCExpr.cpp b/llvm/lib/MC/MCExpr.cpp index 9a4c41699e1..673913f0b82 100644 --- a/llvm/lib/MC/MCExpr.cpp +++ b/llvm/lib/MC/MCExpr.cpp @@ -180,6 +180,7 @@ StringRef MCSymbolRefExpr::getVariantKindName(VariantKind Kind) { case VK_DTPOFF: return "DTPOFF"; case VK_TLVP: return "TLVP"; case VK_SECREL: return "SECREL32"; + case VK_WEAKREF: return "WEAKREF"; case VK_ARM_NONE: return "none"; case VK_ARM_TARGET1: return "target1"; case VK_ARM_TARGET2: return "target2"; @@ -630,17 +631,31 @@ bool MCExpr::EvaluateAsRelocatableImpl(MCValue &Res, case SymbolRef: { const MCSymbolRefExpr *SRE = cast<MCSymbolRefExpr>(this); const MCSymbol &Sym = SRE->getSymbol(); + const MCAsmInfo &MCAsmInfo = SRE->getMCAsmInfo(); // Evaluate recursively if this is a variable. - if (Sym.isVariable() && SRE->getKind() == MCSymbolRefExpr::VK_None) { - bool Ret = Sym.getVariableValue()->EvaluateAsRelocatableImpl(Res, Asm, - Layout, - Addrs, - true); - // If we failed to simplify this to a constant, let the target - // handle it. - if (Ret && !Res.getSymA() && !Res.getSymB()) - return true; + if (Sym.isVariable()) { + if (Sym.getVariableValue()->EvaluateAsRelocatableImpl(Res, Asm, Layout, + Addrs, true)) { + const MCSymbolRefExpr *A = Res.getSymA(); + const MCSymbolRefExpr *B = Res.getSymB(); + + if (MCAsmInfo.hasSubsectionsViaSymbols()) { + // FIXME: This is small hack. Given + // a = b + 4 + // .long a + // the OS X assembler will completely drop the 4. We should probably + // include it in the relocation or produce an error if that is not + // possible. + if (!A && !B) + return true; + } else { + bool IsSymbol = A && A->getSymbol().isDefined(); + bool IsWeakRef = SRE->getKind() == MCSymbolRefExpr::VK_WEAKREF; + if (!IsSymbol && !IsWeakRef) + return true; + } + } } Res = MCValue::get(SRE, 0, 0); |