summaryrefslogtreecommitdiffstats
path: root/llvm/lib/MC/MCExpr.cpp
diff options
context:
space:
mode:
authorRafael Espindola <rafael.espindola@gmail.com>2014-03-20 02:12:01 +0000
committerRafael Espindola <rafael.espindola@gmail.com>2014-03-20 02:12:01 +0000
commit7fadc0ea7df49f4fef7da3797ea382d9486cc259 (patch)
treea240de0de7267b634fd4b36e1e7673f661941f53 /llvm/lib/MC/MCExpr.cpp
parent05c152b5d134a878ae8781d6fc3b8619f387c9de (diff)
downloadbcm5719-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.cpp33
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);
OpenPOWER on IntegriCloud