forked from OSchip/llvm-project
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
This commit is contained in:
parent
05c152b5d1
commit
7fadc0ea7d
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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; }
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@ add_llvm_library(LLVMMC
|
|||
MCELF.cpp
|
||||
MCELFObjectTargetWriter.cpp
|
||||
MCELFStreamer.cpp
|
||||
MCFixup.cpp
|
||||
MCFunction.cpp
|
||||
MCExpr.cpp
|
||||
MCExternalSymbolizer.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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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());
|
||||
}
|
|
@ -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) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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: }
|
||||
|
||||
|
|
|
@ -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: ]
|
Loading…
Reference in New Issue