forked from OSchip/llvm-project
Address the last bit of relocation flag related divergence betweeen
LLVM and binutils. With this patch, there are no functional differences between the .o produced directly from LLVM versus the .s to .o via GNU as, for relocation tags at least, for both PIC and non-PIC modes. Because some non-PIC reloc tags are used (legally) on PIC, so IsPCRel flag is necessary but not sufficient to determine whether the overall codegen mode is PIC or not. Why is this necessary? There is an incompatibility of how relocs are emitted in the .rodata section. Binutils PIC likes to emit certain relocs as section relative offsets. Non-PIC does not do this. So I added a hidden switch on the ELFObjectwriter "-arm-elf-force-pic" which forces the objectwriter to pretend that all relocs are for PIC mode. Todo: Activate ForceARMElfPIC to true if -relocation-model=pic is selected on llc. Todo: There are probably more issues for PIC mode on ARM/MC/ELF... Todo: Existing tests in MC/ARM/elf-reloc*.ll need to be converted over to .s tests as well as expanded to cover the gamut. llvm-svn: 131205
This commit is contained in:
parent
466627ca2e
commit
c09e726455
|
@ -25,6 +25,8 @@
|
|||
#include "llvm/Support/ELF.h"
|
||||
#include "llvm/Target/TargetAsmBackend.h"
|
||||
#include "llvm/ADT/StringSwitch.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/ADT/Statistic.h"
|
||||
|
||||
#include "../Target/X86/X86FixupKinds.h"
|
||||
#include "../Target/ARM/ARMFixupKinds.h"
|
||||
|
@ -32,6 +34,16 @@
|
|||
#include <vector>
|
||||
using namespace llvm;
|
||||
|
||||
#undef DEBUG_TYPE
|
||||
#define DEBUG_TYPE "reloc-info"
|
||||
|
||||
// Emulate the wierd behavior of GNU-as for relocation types
|
||||
namespace llvm {
|
||||
cl::opt<bool>
|
||||
ForceARMElfPIC("arm-elf-force-pic", cl::Hidden, cl::init(false),
|
||||
cl::desc("Force ELF emitter to emit PIC style relocations"));
|
||||
}
|
||||
|
||||
bool ELFObjectWriter::isFixupKindPCRel(const MCAssembler &Asm, unsigned Kind) {
|
||||
const MCFixupKindInfo &FKI =
|
||||
Asm.getBackend().getFixupKindInfo((MCFixupKind) Kind);
|
||||
|
@ -319,7 +331,9 @@ void ELFObjectWriter::WriteSymbolTable(MCDataFragment *SymtabF,
|
|||
|
||||
const MCSymbol *ELFObjectWriter::SymbolToReloc(const MCAssembler &Asm,
|
||||
const MCValue &Target,
|
||||
const MCFragment &F) const {
|
||||
const MCFragment &F,
|
||||
const MCFixup &Fixup,
|
||||
bool IsPCRel) const {
|
||||
const MCSymbol &Symbol = Target.getSymA()->getSymbol();
|
||||
const MCSymbol &ASymbol = Symbol.AliasedSymbol();
|
||||
const MCSymbol *Renamed = Renames.lookup(&Symbol);
|
||||
|
@ -342,7 +356,7 @@ const MCSymbol *ELFObjectWriter::SymbolToReloc(const MCAssembler &Asm,
|
|||
const SectionKind secKind = Section.getKind();
|
||||
|
||||
if (secKind.isBSS())
|
||||
return ExplicitRelSym(Asm, Target, F, true);
|
||||
return ExplicitRelSym(Asm, Target, F, Fixup, IsPCRel);
|
||||
|
||||
if (secKind.isThreadLocal()) {
|
||||
if (Renamed)
|
||||
|
@ -365,13 +379,14 @@ const MCSymbol *ELFObjectWriter::SymbolToReloc(const MCAssembler &Asm,
|
|||
|
||||
if (Section.getFlags() & ELF::SHF_MERGE) {
|
||||
if (Target.getConstant() == 0)
|
||||
return NULL;
|
||||
return ExplicitRelSym(Asm, Target, F, Fixup, IsPCRel);
|
||||
if (Renamed)
|
||||
return Renamed;
|
||||
return &Symbol;
|
||||
}
|
||||
|
||||
return ExplicitRelSym(Asm, Target, F, false);
|
||||
return ExplicitRelSym(Asm, Target, F, Fixup, IsPCRel);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -390,7 +405,7 @@ void ELFObjectWriter::RecordRelocation(const MCAssembler &Asm,
|
|||
if (!Target.isAbsolute()) {
|
||||
const MCSymbol &Symbol = Target.getSymA()->getSymbol();
|
||||
const MCSymbol &ASymbol = Symbol.AliasedSymbol();
|
||||
RelocSymbol = SymbolToReloc(Asm, Target, *Fragment);
|
||||
RelocSymbol = SymbolToReloc(Asm, Target, *Fragment, Fixup, IsPCRel);
|
||||
|
||||
if (const MCSymbolRefExpr *RefB = Target.getSymB()) {
|
||||
const MCSymbol &SymbolB = RefB->getSymbol();
|
||||
|
@ -1261,32 +1276,93 @@ void ARMELFObjectWriter::WriteEFlags() {
|
|||
|
||||
// In ARM, _MergedGlobals and other most symbols get emitted directly.
|
||||
// I.e. not as an offset to a section symbol.
|
||||
// This code is a first-cut approximation of what ARM/gcc does.
|
||||
// This code is an approximation of what ARM/gcc does.
|
||||
|
||||
STATISTIC(PCRelCount, "Total number of PIC Relocations");
|
||||
STATISTIC(NonPCRelCount, "Total number of non-PIC relocations");
|
||||
|
||||
const MCSymbol *ARMELFObjectWriter::ExplicitRelSym(const MCAssembler &Asm,
|
||||
const MCValue &Target,
|
||||
const MCFragment &F,
|
||||
bool IsBSS) const {
|
||||
const MCFixup &Fixup,
|
||||
bool IsPCRel) const {
|
||||
const MCSymbol &Symbol = Target.getSymA()->getSymbol();
|
||||
bool EmitThisSym = false;
|
||||
|
||||
if (IsBSS) {
|
||||
EmitThisSym = StringSwitch<bool>(Symbol.getName())
|
||||
.Case("_MergedGlobals", true)
|
||||
.Default(false);
|
||||
const MCSectionELF &Section =
|
||||
static_cast<const MCSectionELF&>(Symbol.getSection());
|
||||
const SectionKind secKind = Section.getKind();
|
||||
const MCSymbolRefExpr::VariantKind Kind = Target.getSymA()->getKind();
|
||||
MCSymbolRefExpr::VariantKind Kind2;
|
||||
Kind2 = Target.getSymB() ? Target.getSymB()->getKind() :
|
||||
MCSymbolRefExpr::VK_None;
|
||||
bool InNormalSection = true;
|
||||
unsigned RelocType = 0;
|
||||
RelocType = GetRelocTypeInner(Target, Fixup, IsPCRel);
|
||||
|
||||
DEBUG(dbgs() << "considering symbol "
|
||||
<< Section.getSectionName() << "/"
|
||||
<< Symbol.getName() << "/"
|
||||
<< " Rel:" << (unsigned)RelocType
|
||||
<< " Kind: " << (int)Kind << "/" << (int)Kind2
|
||||
<< " Tmp:"
|
||||
<< Symbol.isAbsolute() << "/" << Symbol.isDefined() << "/"
|
||||
<< Symbol.isVariable() << "/" << Symbol.isTemporary()
|
||||
<< " Counts:" << PCRelCount << "/" << NonPCRelCount << "\n");
|
||||
|
||||
if (IsPCRel || ForceARMElfPIC) { ++PCRelCount;
|
||||
switch (RelocType) {
|
||||
default:
|
||||
// Most relocation types are emitted as explicit symbols
|
||||
InNormalSection =
|
||||
StringSwitch<bool>(Section.getSectionName())
|
||||
.Case(".data.rel.ro.local", false)
|
||||
.Case(".data.rel", false)
|
||||
.Case(".bss", false)
|
||||
.Default(true);
|
||||
EmitThisSym = true;
|
||||
break;
|
||||
case ELF::R_ARM_ABS32:
|
||||
// But things get strange with R_ARM_ABS32
|
||||
// In this case, most things that go in .rodata show up
|
||||
// as section relative relocations
|
||||
InNormalSection =
|
||||
StringSwitch<bool>(Section.getSectionName())
|
||||
.Case(".data.rel.ro.local", false)
|
||||
.Case(".data.rel", false)
|
||||
.Case(".rodata", false)
|
||||
.Case(".bss", false)
|
||||
.Default(true);
|
||||
EmitThisSym = false;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
EmitThisSym = StringSwitch<bool>(Symbol.getName())
|
||||
.Case("_MergedGlobals", true)
|
||||
.StartsWith(".L.str", true)
|
||||
.Default(false);
|
||||
NonPCRelCount++;
|
||||
InNormalSection =
|
||||
StringSwitch<bool>(Section.getSectionName())
|
||||
.Case(".data.rel.ro.local", false)
|
||||
.Case(".rodata", false)
|
||||
.Case(".data.rel", false)
|
||||
.Case(".bss", false)
|
||||
.Default(true);
|
||||
|
||||
switch (RelocType) {
|
||||
default: EmitThisSym = true; break;
|
||||
case ELF::R_ARM_ABS32: EmitThisSym = false; break;
|
||||
}
|
||||
}
|
||||
|
||||
if (EmitThisSym)
|
||||
return &Symbol;
|
||||
if (! Symbol.isTemporary())
|
||||
if (! Symbol.isTemporary() && InNormalSection) {
|
||||
return &Symbol;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Need to examine the Fixup when determining whether to
|
||||
// emit the relocation as an explicit symbol or as a section relative
|
||||
// offset
|
||||
unsigned ARMELFObjectWriter::GetRelocType(const MCValue &Target,
|
||||
const MCFixup &Fixup,
|
||||
bool IsPCRel,
|
||||
|
@ -1295,6 +1371,20 @@ unsigned ARMELFObjectWriter::GetRelocType(const MCValue &Target,
|
|||
MCSymbolRefExpr::VariantKind Modifier = Target.isAbsolute() ?
|
||||
MCSymbolRefExpr::VK_None : Target.getSymA()->getKind();
|
||||
|
||||
unsigned Type = GetRelocTypeInner(Target, Fixup, IsPCRel);
|
||||
|
||||
if (RelocNeedsGOT(Modifier))
|
||||
NeedsGOT = true;
|
||||
|
||||
return Type;
|
||||
}
|
||||
|
||||
unsigned ARMELFObjectWriter::GetRelocTypeInner(const MCValue &Target,
|
||||
const MCFixup &Fixup,
|
||||
bool IsPCRel) const {
|
||||
MCSymbolRefExpr::VariantKind Modifier = Target.isAbsolute() ?
|
||||
MCSymbolRefExpr::VK_None : Target.getSymA()->getKind();
|
||||
|
||||
unsigned Type = 0;
|
||||
if (IsPCRel) {
|
||||
switch ((unsigned)Fixup.getKind()) {
|
||||
|
@ -1303,7 +1393,7 @@ unsigned ARMELFObjectWriter::GetRelocType(const MCValue &Target,
|
|||
switch (Modifier) {
|
||||
default: llvm_unreachable("Unsupported Modifier");
|
||||
case MCSymbolRefExpr::VK_None:
|
||||
Type = ELF::R_ARM_BASE_PREL;
|
||||
Type = ELF::R_ARM_REL32;
|
||||
break;
|
||||
case MCSymbolRefExpr::VK_ARM_TLSGD:
|
||||
assert(0 && "unimplemented");
|
||||
|
@ -1399,9 +1489,6 @@ unsigned ARMELFObjectWriter::GetRelocType(const MCValue &Target,
|
|||
}
|
||||
}
|
||||
|
||||
if (RelocNeedsGOT(Modifier))
|
||||
NeedsGOT = true;
|
||||
|
||||
return Type;
|
||||
}
|
||||
|
||||
|
|
|
@ -140,15 +140,18 @@ class ELFObjectWriter : public MCObjectWriter {
|
|||
unsigned ShstrtabIndex;
|
||||
|
||||
|
||||
const MCSymbol *SymbolToReloc(const MCAssembler &Asm,
|
||||
const MCValue &Target,
|
||||
const MCFragment &F) const;
|
||||
virtual const MCSymbol *SymbolToReloc(const MCAssembler &Asm,
|
||||
const MCValue &Target,
|
||||
const MCFragment &F,
|
||||
const MCFixup &Fixup,
|
||||
bool IsPCRel) const;
|
||||
|
||||
// For arch-specific emission of explicit reloc symbol
|
||||
virtual const MCSymbol *ExplicitRelSym(const MCAssembler &Asm,
|
||||
const MCValue &Target,
|
||||
const MCFragment &F,
|
||||
bool IsBSS) const {
|
||||
const MCFixup &Fixup,
|
||||
bool IsPCRel) const {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -380,11 +383,16 @@ class ELFObjectWriter : public MCObjectWriter {
|
|||
virtual const MCSymbol *ExplicitRelSym(const MCAssembler &Asm,
|
||||
const MCValue &Target,
|
||||
const MCFragment &F,
|
||||
bool IsBSS) const;
|
||||
const MCFixup &Fixup,
|
||||
bool IsPCRel) const;
|
||||
|
||||
virtual unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup,
|
||||
bool IsPCRel, bool IsRelocWithSymbol,
|
||||
int64_t Addend);
|
||||
private:
|
||||
unsigned GetRelocTypeInner(const MCValue &Target,
|
||||
const MCFixup &Fixup, bool IsPCRel) const;
|
||||
|
||||
};
|
||||
|
||||
//===- MBlazeELFObjectWriter -------------------------------------------===//
|
||||
|
|
Loading…
Reference in New Issue