aboutsummaryrefslogtreecommitdiffstats
path: root/lib/MC/ELFObjectWriter.cpp
diff options
context:
space:
mode:
authorNowar Gu <nowar100@gmail.com>2011-06-17 14:29:24 +0800
committerNowar Gu <nowar100@gmail.com>2011-06-20 15:49:07 +0800
commit907af0f20f58f2ea26da7ea64e1f094cd6880db7 (patch)
tree02007757de416c561df174d582205cebfa582801 /lib/MC/ELFObjectWriter.cpp
parent1d4f9a57447faa0142a1d0301e5ce550cfe60c4f (diff)
parentec324e5ae44025c6bdb930b78198f30f807e355b (diff)
downloadexternal_llvm-907af0f20f58f2ea26da7ea64e1f094cd6880db7.zip
external_llvm-907af0f20f58f2ea26da7ea64e1f094cd6880db7.tar.gz
external_llvm-907af0f20f58f2ea26da7ea64e1f094cd6880db7.tar.bz2
Merge upstream to r133240 at Fri. 17th Jun 2011.
Conflicts: lib/CodeGen/AsmPrinter/AsmPrinter.cpp lib/Target/ARM/ARMCodeEmitter.cpp
Diffstat (limited to 'lib/MC/ELFObjectWriter.cpp')
-rw-r--r--lib/MC/ELFObjectWriter.cpp151
1 files changed, 128 insertions, 23 deletions
diff --git a/lib/MC/ELFObjectWriter.cpp b/lib/MC/ELFObjectWriter.cpp
index b7d30cd..59e1b8e 100644
--- a/lib/MC/ELFObjectWriter.cpp
+++ b/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;
}
@@ -1476,13 +1574,17 @@ unsigned X86ELFObjectWriter::GetRelocType(const MCValue &Target,
if (IsPCRel) {
switch ((unsigned)Fixup.getKind()) {
default: llvm_unreachable("invalid fixup kind!");
+
+ case FK_Data_8: Type = ELF::R_X86_64_PC64; break;
+ case FK_Data_4: Type = ELF::R_X86_64_PC32; break;
+ case FK_Data_2: Type = ELF::R_X86_64_PC16; break;
+
case FK_PCRel_8:
assert(Modifier == MCSymbolRefExpr::VK_None);
Type = ELF::R_X86_64_PC64;
break;
case X86::reloc_signed_4byte:
case X86::reloc_riprel_4byte_movq_load:
- case FK_Data_4: // FIXME?
case X86::reloc_riprel_4byte:
case FK_PCRel_4:
switch (Modifier) {
@@ -1609,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;