summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/llvm/MC/MCELFSymbolFlags.h3
-rw-r--r--include/llvm/MC/MCExpr.h1
-rw-r--r--include/llvm/MC/MCFixup.h3
-rw-r--r--lib/MC/CMakeLists.txt1
-rw-r--r--lib/MC/ELFObjectWriter.cpp14
-rw-r--r--lib/MC/MCELFStreamer.cpp5
-rw-r--r--lib/MC/MCExpr.cpp33
-rw-r--r--lib/MC/MCFixup.cpp36
-rw-r--r--lib/Target/ARM/MCTargetDesc/ARMELFObjectWriter.cpp12
-rw-r--r--lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp33
-rw-r--r--lib/Target/SystemZ/MCTargetDesc/SystemZMCObjectWriter.cpp4
-rw-r--r--lib/Target/X86/MCTargetDesc/X86ELFObjectWriter.cpp3
-rw-r--r--test/MC/ELF/relocation.s4
-rw-r--r--test/MC/X86/reloc-undef-global.s20
14 files changed, 137 insertions, 35 deletions
diff --git a/include/llvm/MC/MCELFSymbolFlags.h b/include/llvm/MC/MCELFSymbolFlags.h
index 782e7d6126..5b82a58f40 100644
--- a/include/llvm/MC/MCELFSymbolFlags.h
+++ b/include/llvm/MC/MCELFSymbolFlags.h
@@ -51,8 +51,7 @@ namespace llvm {
ELF_STV_Hidden = (ELF::STV_HIDDEN << ELF_STV_Shift),
ELF_STV_Protected = (ELF::STV_PROTECTED << ELF_STV_Shift),
- ELF_Other_Weakref = (1 << ELF_Other_Shift),
- ELF_Other_ThumbFunc = (2 << ELF_Other_Shift)
+ ELF_Other_ThumbFunc = (1 << ELF_Other_Shift)
};
} // end namespace llvm
diff --git a/include/llvm/MC/MCExpr.h b/include/llvm/MC/MCExpr.h
index a822513ffd..b1d68ecb9f 100644
--- a/include/llvm/MC/MCExpr.h
+++ b/include/llvm/MC/MCExpr.h
@@ -160,6 +160,7 @@ public:
VK_DTPOFF,
VK_TLVP, // Mach-O thread local variable relocation
VK_SECREL,
+ VK_WEAKREF, // The link between the symbols in .weakref foo, bar
VK_ARM_NONE,
VK_ARM_TARGET1,
diff --git a/include/llvm/MC/MCFixup.h b/include/llvm/MC/MCFixup.h
index 16e9eb730b..e6d675fba3 100644
--- a/include/llvm/MC/MCFixup.h
+++ b/include/llvm/MC/MCFixup.h
@@ -10,6 +10,7 @@
#ifndef LLVM_MC_MCFIXUP_H
#define LLVM_MC_MCFIXUP_H
+#include "llvm/MC/MCExpr.h"
#include "llvm/Support/DataTypes.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/SMLoc.h"
@@ -87,6 +88,8 @@ public:
MCFixupKind getKind() const { return MCFixupKind(Kind); }
+ MCSymbolRefExpr::VariantKind getAccessVariant() const;
+
uint32_t getOffset() const { return Offset; }
void setOffset(uint32_t Value) { Offset = Value; }
diff --git a/lib/MC/CMakeLists.txt b/lib/MC/CMakeLists.txt
index 06099640a1..eb3f9e52d7 100644
--- a/lib/MC/CMakeLists.txt
+++ b/lib/MC/CMakeLists.txt
@@ -16,6 +16,7 @@ add_llvm_library(LLVMMC
MCELF.cpp
MCELFObjectTargetWriter.cpp
MCELFStreamer.cpp
+ MCFixup.cpp
MCFunction.cpp
MCExpr.cpp
MCExternalSymbolizer.cpp
diff --git a/lib/MC/ELFObjectWriter.cpp b/lib/MC/ELFObjectWriter.cpp
index 909ea80083..1dae2f467d 100644
--- a/lib/MC/ELFObjectWriter.cpp
+++ b/lib/MC/ELFObjectWriter.cpp
@@ -778,7 +778,7 @@ void ELFObjectWriter::RecordRelocation(const MCAssembler &Asm,
Index = 0;
}
} else {
- if (Asm.getSymbolData(Symbol).getFlags() & ELF_Other_Weakref)
+ if (Target.getSymA()->getKind() == MCSymbolRefExpr::VK_WEAKREF)
WeakrefUsedInReloc.insert(RelocSymbol);
else
UsedInReloc.insert(RelocSymbol);
@@ -823,8 +823,14 @@ ELFObjectWriter::getSymbolIndexInSymbolTable(const MCAssembler &Asm,
bool ELFObjectWriter::isInSymtab(const MCAssembler &Asm,
const MCSymbolData &Data,
bool Used, bool Renamed) {
- if (Data.getFlags() & ELF_Other_Weakref)
- return false;
+ const MCSymbol &Symbol = Data.getSymbol();
+ if (Symbol.isVariable()) {
+ const MCExpr *Expr = Symbol.getVariableValue();
+ if (const MCSymbolRefExpr *Ref = dyn_cast<MCSymbolRefExpr>(Expr)) {
+ if (Ref->getKind() == MCSymbolRefExpr::VK_WEAKREF)
+ return false;
+ }
+ }
if (Used)
return true;
@@ -832,8 +838,6 @@ bool ELFObjectWriter::isInSymtab(const MCAssembler &Asm,
if (Renamed)
return false;
- const MCSymbol &Symbol = Data.getSymbol();
-
if (Symbol.getName() == "_GLOBAL_OFFSET_TABLE_")
return true;
diff --git a/lib/MC/MCELFStreamer.cpp b/lib/MC/MCELFStreamer.cpp
index 5f6a889769..d07ef9e698 100644
--- a/lib/MC/MCELFStreamer.cpp
+++ b/lib/MC/MCELFStreamer.cpp
@@ -99,9 +99,8 @@ void MCELFStreamer::ChangeSection(const MCSection *Section,
void MCELFStreamer::EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) {
getAssembler().getOrCreateSymbolData(*Symbol);
- MCSymbolData &AliasSD = getAssembler().getOrCreateSymbolData(*Alias);
- AliasSD.setFlags(AliasSD.getFlags() | ELF_Other_Weakref);
- const MCExpr *Value = MCSymbolRefExpr::Create(Symbol, getContext());
+ const MCExpr *Value = MCSymbolRefExpr::Create(
+ Symbol, MCSymbolRefExpr::VK_WEAKREF, getContext());
Alias->setVariableValue(Value);
}
diff --git a/lib/MC/MCExpr.cpp b/lib/MC/MCExpr.cpp
index 9a4c41699e..673913f0b8 100644
--- a/lib/MC/MCExpr.cpp
+++ b/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);
diff --git a/lib/MC/MCFixup.cpp b/lib/MC/MCFixup.cpp
new file mode 100644
index 0000000000..d0a4fed28f
--- /dev/null
+++ b/lib/MC/MCFixup.cpp
@@ -0,0 +1,36 @@
+//===- 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());
+}
diff --git a/lib/Target/ARM/MCTargetDesc/ARMELFObjectWriter.cpp b/lib/Target/ARM/MCTargetDesc/ARMELFObjectWriter.cpp
index 25efd67c69..d829394e09 100644
--- a/lib/Target/ARM/MCTargetDesc/ARMELFObjectWriter.cpp
+++ b/lib/Target/ARM/MCTargetDesc/ARMELFObjectWriter.cpp
@@ -71,17 +71,16 @@ const MCSymbol *ARMELFObjectWriter::ExplicitRelSym(const MCAssembler &Asm,
bool InNormalSection = true;
unsigned RelocType = 0;
RelocType = GetRelocTypeInner(Target, Fixup, IsPCRel);
+ assert(!Target.getSymB() ||
+ Target.getSymB()->getKind() == MCSymbolRefExpr::VK_None);
DEBUG(
- const MCSymbolRefExpr::VariantKind Kind = Target.getSymA()->getKind();
- MCSymbolRefExpr::VariantKind Kind2;
- Kind2 = Target.getSymB() ? Target.getSymB()->getKind() :
- MCSymbolRefExpr::VK_None;
+ MCSymbolRefExpr::VariantKind Kind = Fixup.getAccessVariant();
dbgs() << "considering symbol "
<< Section.getSectionName() << "/"
<< Symbol.getName() << "/"
<< " Rel:" << (unsigned)RelocType
- << " Kind: " << (int)Kind << "/" << (int)Kind2
+ << " Kind: " << (int)Kind
<< " Tmp:"
<< Symbol.isAbsolute() << "/" << Symbol.isDefined() << "/"
<< Symbol.isVariable() << "/" << Symbol.isTemporary()
@@ -152,8 +151,7 @@ unsigned ARMELFObjectWriter::GetRelocType(const MCValue &Target,
unsigned ARMELFObjectWriter::GetRelocTypeInner(const MCValue &Target,
const MCFixup &Fixup,
bool IsPCRel) const {
- MCSymbolRefExpr::VariantKind Modifier = Target.isAbsolute() ?
- MCSymbolRefExpr::VK_None : Target.getSymA()->getKind();
+ MCSymbolRefExpr::VariantKind Modifier = Fixup.getAccessVariant();
unsigned Type = 0;
if (IsPCRel) {
diff --git a/lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp b/lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp
index 54de70eff7..1e3d4b71ae 100644
--- a/lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp
+++ b/lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp
@@ -9,6 +9,7 @@
#include "MCTargetDesc/PPCMCTargetDesc.h"
#include "MCTargetDesc/PPCFixupKinds.h"
+#include "MCTargetDesc/PPCMCExpr.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/MC/MCELFObjectWriter.h"
#include "llvm/MC/MCExpr.h"
@@ -49,12 +50,37 @@ PPCELFObjectWriter::PPCELFObjectWriter(bool Is64Bit, uint8_t OSABI)
PPCELFObjectWriter::~PPCELFObjectWriter() {
}
+static MCSymbolRefExpr::VariantKind getAccessVariant(const MCFixup &Fixup) {
+ const MCExpr *Expr = Fixup.getValue();
+
+ if (Expr->getKind() != MCExpr::Target)
+ return Fixup.getAccessVariant();
+
+ switch (cast<PPCMCExpr>(Expr)->getKind()) {
+ case PPCMCExpr::VK_PPC_None:
+ return MCSymbolRefExpr::VK_None;
+ case PPCMCExpr::VK_PPC_LO:
+ return MCSymbolRefExpr::VK_PPC_LO;
+ case PPCMCExpr::VK_PPC_HI:
+ return MCSymbolRefExpr::VK_PPC_HI;
+ case PPCMCExpr::VK_PPC_HA:
+ return MCSymbolRefExpr::VK_PPC_HA;
+ case PPCMCExpr::VK_PPC_HIGHERA:
+ return MCSymbolRefExpr::VK_PPC_HIGHERA;
+ case PPCMCExpr::VK_PPC_HIGHER:
+ return MCSymbolRefExpr::VK_PPC_HIGHER;
+ case PPCMCExpr::VK_PPC_HIGHEST:
+ return MCSymbolRefExpr::VK_PPC_HIGHEST;
+ case PPCMCExpr::VK_PPC_HIGHESTA:
+ return MCSymbolRefExpr::VK_PPC_HIGHESTA;
+ }
+}
+
unsigned PPCELFObjectWriter::getRelocTypeInner(const MCValue &Target,
const MCFixup &Fixup,
bool IsPCRel) const
{
- MCSymbolRefExpr::VariantKind Modifier = Target.isAbsolute() ?
- MCSymbolRefExpr::VK_None : Target.getSymA()->getKind();
+ MCSymbolRefExpr::VariantKind Modifier = getAccessVariant(Fixup);
// determine the type of the relocation
unsigned Type;
@@ -368,8 +394,7 @@ const MCSymbol *PPCELFObjectWriter::ExplicitRelSym(const MCAssembler &Asm,
const MCFixup &Fixup,
bool IsPCRel) const {
assert(Target.getSymA() && "SymA cannot be 0");
- MCSymbolRefExpr::VariantKind Modifier = Target.isAbsolute() ?
- MCSymbolRefExpr::VK_None : Target.getSymA()->getKind();
+ MCSymbolRefExpr::VariantKind Modifier = Fixup.getAccessVariant();
bool EmitThisSym;
switch (Modifier) {
diff --git a/lib/Target/SystemZ/MCTargetDesc/SystemZMCObjectWriter.cpp b/lib/Target/SystemZ/MCTargetDesc/SystemZMCObjectWriter.cpp
index 217a51cea4..ddc1379e34 100644
--- a/lib/Target/SystemZ/MCTargetDesc/SystemZMCObjectWriter.cpp
+++ b/lib/Target/SystemZ/MCTargetDesc/SystemZMCObjectWriter.cpp
@@ -88,9 +88,7 @@ unsigned SystemZObjectWriter::GetRelocType(const MCValue &Target,
bool IsPCRel,
bool IsRelocWithSymbol,
int64_t Addend) const {
- MCSymbolRefExpr::VariantKind Modifier = (Target.isAbsolute() ?
- MCSymbolRefExpr::VK_None :
- Target.getSymA()->getKind());
+ MCSymbolRefExpr::VariantKind Modifier = Fixup.getAccessVariant();
unsigned Kind = Fixup.getKind();
switch (Modifier) {
case MCSymbolRefExpr::VK_None:
diff --git a/lib/Target/X86/MCTargetDesc/X86ELFObjectWriter.cpp b/lib/Target/X86/MCTargetDesc/X86ELFObjectWriter.cpp
index 7118a6f6dc..618b0e6e1e 100644
--- a/lib/Target/X86/MCTargetDesc/X86ELFObjectWriter.cpp
+++ b/lib/Target/X86/MCTargetDesc/X86ELFObjectWriter.cpp
@@ -46,8 +46,7 @@ unsigned X86ELFObjectWriter::GetRelocType(const MCValue &Target,
int64_t Addend) const {
// determine the type of the relocation
- MCSymbolRefExpr::VariantKind Modifier = Target.isAbsolute() ?
- MCSymbolRefExpr::VK_None : Target.getSymA()->getKind();
+ MCSymbolRefExpr::VariantKind Modifier = Fixup.getAccessVariant();
unsigned Type;
if (getEMachine() == ELF::EM_X86_64) {
if (IsPCRel) {
diff --git a/test/MC/ELF/relocation.s b/test/MC/ELF/relocation.s
index 6bac5913b6..d2ee6afda3 100644
--- a/test/MC/ELF/relocation.s
+++ b/test/MC/ELF/relocation.s
@@ -25,6 +25,9 @@ bar:
.word foo-bar
.byte foo-bar
+ zed = foo +2
+ call zed@PLT
+
// CHECK: Section {
// CHECK: Name: .rela.text
// CHECK: Relocations [
@@ -49,6 +52,7 @@ bar:
// 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 foo 0xFFFFFFFFFFFFFFFE
// CHECK-NEXT: ]
// CHECK-NEXT: }
diff --git a/test/MC/X86/reloc-undef-global.s b/test/MC/X86/reloc-undef-global.s
new file mode 100644
index 0000000000..a4854d4a35
--- /dev/null
+++ b/test/MC/X86/reloc-undef-global.s
@@ -0,0 +1,20 @@
+// RUN: llvm-mc -filetype=obj -triple x86_64-pc-linux %s -o - | llvm-readobj -r | FileCheck --check-prefix=ELF %s
+// RUN: llvm-mc -filetype=obj -triple x86_64-apple-darwin %s -o - | llvm-readobj -r | FileCheck --check-prefix=MACHO %s
+
+
+bar = foo + 4
+ .globl bar
+ .long bar
+
+// ELF: Relocations [
+// ELF-NEXT: Section (2) .rela.text {
+// ELF-NEXT: 0x0 R_X86_64_32 foo 0x4
+// ELF-NEXT: }
+// ELF-NEXT: ]
+
+
+// MACHO: Relocations [
+// MACHO: Section __text {
+// MACHO: 0x0 0 2 1 X86_64_RELOC_UNSIGNED 0 bar
+// MACHO: }
+// MACHO: ]