llvm-6502/lib/MC/MCFixup.cpp
Rafael Espindola 0a70f9b3b9 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.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@204294 91177308-0d34-0410-b5e6-96231b3b80d8
2014-03-20 02:12:01 +00:00

37 lines
1.1 KiB
C++

//===- MCFixup.cpp - Assembly Fixup Implementation ------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "llvm/MC/MCFixup.h"
using namespace llvm;
static MCSymbolRefExpr::VariantKind getAccessVariant(const MCExpr *Expr) {
switch (Expr->getKind()) {
case MCExpr::Unary:
case MCExpr::Target:
llvm_unreachable("unsupported");
case MCExpr::Constant:
return MCSymbolRefExpr::VK_None;
case MCExpr::SymbolRef: {
const MCSymbolRefExpr *SRE = cast<MCSymbolRefExpr>(Expr);
return SRE->getKind();
}
case MCExpr::Binary: {
const MCBinaryExpr *ABE = cast<MCBinaryExpr>(Expr);
assert(getAccessVariant(ABE->getRHS()) == MCSymbolRefExpr::VK_None);
return getAccessVariant(ABE->getLHS());
}
}
}
MCSymbolRefExpr::VariantKind MCFixup::getAccessVariant() const {
return ::getAccessVariant(getValue());
}