diff options
author | dim <dim@FreeBSD.org> | 2011-06-12 18:01:31 +0000 |
---|---|---|
committer | dim <dim@FreeBSD.org> | 2011-06-12 18:01:31 +0000 |
commit | d4c7939beafe09c033866ebd290e274af0cc826d (patch) | |
tree | a9b264321873e7d25e69b8671c9f705ebc6d30ee /contrib/llvm/lib/MC/ELFObjectWriter.cpp | |
parent | b164882ef981a8ed5c085469231831e221fa1323 (diff) | |
parent | ece02cd5829cea836e9365b0845a8ef042d17b0a (diff) | |
download | FreeBSD-src-d4c7939beafe09c033866ebd290e274af0cc826d.zip FreeBSD-src-d4c7939beafe09c033866ebd290e274af0cc826d.tar.gz |
Upgrade our copy of llvm/clang to r132879, from upstream's trunk.
Diffstat (limited to 'contrib/llvm/lib/MC/ELFObjectWriter.cpp')
-rw-r--r-- | contrib/llvm/lib/MC/ELFObjectWriter.cpp | 145 |
1 files changed, 123 insertions, 22 deletions
diff --git a/contrib/llvm/lib/MC/ELFObjectWriter.cpp b/contrib/llvm/lib/MC/ELFObjectWriter.cpp index 23c6d4c..59e1b8e 100644 --- a/contrib/llvm/lib/MC/ELFObjectWriter.cpp +++ b/contrib/llvm/lib/MC/ELFObjectWriter.cpp @@ -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,9 @@ #include <vector> using namespace llvm; +#undef DEBUG_TYPE +#define DEBUG_TYPE "reloc-info" + bool ELFObjectWriter::isFixupKindPCRel(const MCAssembler &Asm, unsigned Kind) { const MCFixupKindInfo &FKI = Asm.getBackend().getFixupKindInfo((MCFixupKind) Kind); @@ -46,6 +51,7 @@ bool ELFObjectWriter::RelocNeedsGOT(MCSymbolRefExpr::VariantKind Variant) { case MCSymbolRefExpr::VK_GOT: case MCSymbolRefExpr::VK_PLT: case MCSymbolRefExpr::VK_GOTPCREL: + case MCSymbolRefExpr::VK_GOTOFF: case MCSymbolRefExpr::VK_TPOFF: case MCSymbolRefExpr::VK_TLSGD: case MCSymbolRefExpr::VK_GOTTPOFF: @@ -181,8 +187,13 @@ uint64_t ELFObjectWriter::SymbolValue(MCSymbolData &Data, if (!Symbol.isInSection()) return 0; - if (Data.getFragment()) - return Layout.getSymbolOffset(&Data); + + if (Data.getFragment()) { + if (Data.getFlags() & ELF_Other_ThumbFunc) + return Layout.getSymbolOffset(&Data)+1; + else + return Layout.getSymbolOffset(&Data); + } return 0; } @@ -319,7 +330,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 +355,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 +378,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 +404,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(); @@ -532,6 +546,7 @@ void ELFObjectWriter::ComputeSymbolTable(MCAssembler &Asm, RevGroupMapTy RevGroupMap, unsigned NumRegularSections) { // FIXME: Is this the correct place to do this? + // FIXME: Why is an undefined reference to _GLOBAL_OFFSET_TABLE_ needed? if (NeedsGOT) { llvm::StringRef Name = "_GLOBAL_OFFSET_TABLE_"; MCSymbol *Sym = Asm.getContext().GetOrCreateSymbol(Name); @@ -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()); + bool InNormalSection = true; + unsigned RelocType = 0; + RelocType = GetRelocTypeInner(Target, Fixup, IsPCRel); + + DEBUG( + const MCSymbolRefExpr::VariantKind Kind = Target.getSymA()->getKind(); + MCSymbolRefExpr::VariantKind Kind2; + Kind2 = Target.getSymB() ? Target.getSymB()->getKind() : + MCSymbolRefExpr::VK_None; + 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) { ++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"); @@ -1342,6 +1432,17 @@ unsigned ARMELFObjectWriter::GetRelocType(const MCValue &Target, case ARM::fixup_t2_movw_lo16_pcrel: Type = ELF::R_ARM_THM_MOVW_PREL_NC; break; + case ARM::fixup_arm_thumb_bl: + case ARM::fixup_arm_thumb_blx: + switch (Modifier) { + case MCSymbolRefExpr::VK_ARM_PLT: + Type = ELF::R_ARM_THM_CALL; + break; + default: + Type = ELF::R_ARM_NONE; + break; + } + break; } } else { switch ((unsigned)Fixup.getKind()) { @@ -1399,9 +1500,6 @@ unsigned ARMELFObjectWriter::GetRelocType(const MCValue &Target, } } - if (RelocNeedsGOT(Modifier)) - NeedsGOT = true; - return Type; } @@ -1613,6 +1711,9 @@ unsigned X86ELFObjectWriter::GetRelocType(const MCValue &Target, case MCSymbolRefExpr::VK_DTPOFF: Type = ELF::R_386_TLS_LDO_32; break; + case MCSymbolRefExpr::VK_GOTTPOFF: + Type = ELF::R_386_TLS_IE_32; + break; } break; case FK_Data_2: Type = ELF::R_386_16; break; |