Move the ARM specific parts of the ELF writer to Target/ARM.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@147115 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Rafael Espindola 2011-12-22 00:37:50 +00:00
parent e99183d2ac
commit 69bbda0391
7 changed files with 316 additions and 275 deletions

View File

@ -43,6 +43,12 @@ public:
virtual unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup,
bool IsPCRel, bool IsRelocWithSymbol,
int64_t Addend) const; // FIXME: add = 0
virtual unsigned getEFlags() const;
virtual const MCSymbol *ExplicitRelSym(const MCAssembler &Asm,
const MCValue &Target,
const MCFragment &F,
const MCFixup &Fixup,
bool IsPCRel) const;
/// @name Accessors
/// @{

View File

@ -25,11 +25,9 @@
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/ELF.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/StringSwitch.h"
#include "../Target/Mips/MCTargetDesc/MipsFixupKinds.h"
#include "../Target/ARM/MCTargetDesc/ARMFixupKinds.h"
#include "../Target/PowerPC/MCTargetDesc/PPCFixupKinds.h"
#include <vector>
@ -1260,9 +1258,8 @@ MCObjectWriter *llvm::createELFObjectWriter(MCELFObjectTargetWriter *MOTW,
switch (MOTW->getEMachine()) {
case ELF::EM_386:
case ELF::EM_X86_64:
return new ELFObjectWriter(MOTW, OS, IsLittleEndian); break;
case ELF::EM_ARM:
return new ARMELFObjectWriter(MOTW, OS, IsLittleEndian); break;
return new ELFObjectWriter(MOTW, OS, IsLittleEndian); break;
case ELF::EM_MBLAZE:
return new MBlazeELFObjectWriter(MOTW, OS, IsLittleEndian); break;
case ELF::EM_PPC:
@ -1284,243 +1281,6 @@ unsigned ELFObjectWriter::GetRelocType(const MCValue &Target,
}
/// START OF SUBCLASSES for ELFObjectWriter
//===- ARMELFObjectWriter -------------------------------------------===//
ARMELFObjectWriter::ARMELFObjectWriter(MCELFObjectTargetWriter *MOTW,
raw_ostream &_OS,
bool IsLittleEndian)
: ELFObjectWriter(MOTW, _OS, IsLittleEndian)
{}
ARMELFObjectWriter::~ARMELFObjectWriter()
{}
// FIXME: get the real EABI Version from the Triple.
unsigned ARMELFObjectWriter::getEFlags() const {
return ELF::EF_ARM_EABIMASK & DefaultEABIVersion;
}
// In ARM, _MergedGlobals and other most symbols get emitted directly.
// I.e. not as an offset to a section symbol.
// 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,
const MCFixup &Fixup,
bool IsPCRel) const {
const MCSymbol &Symbol = Target.getSymA()->getSymbol();
bool EmitThisSym = 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 {
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() && 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,
bool IsRelocWithSymbol,
int64_t Addend) const {
return GetRelocTypeInner(Target, Fixup, IsPCRel);
}
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()) {
default: assert(0 && "Unimplemented");
case FK_Data_4:
switch (Modifier) {
default: llvm_unreachable("Unsupported Modifier");
case MCSymbolRefExpr::VK_None:
Type = ELF::R_ARM_REL32;
break;
case MCSymbolRefExpr::VK_ARM_TLSGD:
assert(0 && "unimplemented");
break;
case MCSymbolRefExpr::VK_ARM_GOTTPOFF:
Type = ELF::R_ARM_TLS_IE32;
break;
}
break;
case ARM::fixup_arm_uncondbranch:
switch (Modifier) {
case MCSymbolRefExpr::VK_ARM_PLT:
Type = ELF::R_ARM_PLT32;
break;
default:
Type = ELF::R_ARM_CALL;
break;
}
break;
case ARM::fixup_arm_condbranch:
Type = ELF::R_ARM_JUMP24;
break;
case ARM::fixup_arm_movt_hi16:
case ARM::fixup_arm_movt_hi16_pcrel:
Type = ELF::R_ARM_MOVT_PREL;
break;
case ARM::fixup_arm_movw_lo16:
case ARM::fixup_arm_movw_lo16_pcrel:
Type = ELF::R_ARM_MOVW_PREL_NC;
break;
case ARM::fixup_t2_movt_hi16:
case ARM::fixup_t2_movt_hi16_pcrel:
Type = ELF::R_ARM_THM_MOVT_PREL;
break;
case ARM::fixup_t2_movw_lo16:
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()) {
default: llvm_unreachable("invalid fixup kind!");
case FK_Data_4:
switch (Modifier) {
default: llvm_unreachable("Unsupported Modifier"); break;
case MCSymbolRefExpr::VK_ARM_GOT:
Type = ELF::R_ARM_GOT_BREL;
break;
case MCSymbolRefExpr::VK_ARM_TLSGD:
Type = ELF::R_ARM_TLS_GD32;
break;
case MCSymbolRefExpr::VK_ARM_TPOFF:
Type = ELF::R_ARM_TLS_LE32;
break;
case MCSymbolRefExpr::VK_ARM_GOTTPOFF:
Type = ELF::R_ARM_TLS_IE32;
break;
case MCSymbolRefExpr::VK_None:
Type = ELF::R_ARM_ABS32;
break;
case MCSymbolRefExpr::VK_ARM_GOTOFF:
Type = ELF::R_ARM_GOTOFF32;
break;
}
break;
case ARM::fixup_arm_ldst_pcrel_12:
case ARM::fixup_arm_pcrel_10:
case ARM::fixup_arm_adr_pcrel_12:
case ARM::fixup_arm_thumb_bl:
case ARM::fixup_arm_thumb_cb:
case ARM::fixup_arm_thumb_cp:
case ARM::fixup_arm_thumb_br:
assert(0 && "Unimplemented");
break;
case ARM::fixup_arm_uncondbranch:
Type = ELF::R_ARM_CALL;
break;
case ARM::fixup_arm_condbranch:
Type = ELF::R_ARM_JUMP24;
break;
case ARM::fixup_arm_movt_hi16:
Type = ELF::R_ARM_MOVT_ABS;
break;
case ARM::fixup_arm_movw_lo16:
Type = ELF::R_ARM_MOVW_ABS_NC;
break;
case ARM::fixup_t2_movt_hi16:
Type = ELF::R_ARM_THM_MOVT_ABS;
break;
case ARM::fixup_t2_movw_lo16:
Type = ELF::R_ARM_THM_MOVW_ABS_NC;
break;
}
}
return Type;
}
//===- PPCELFObjectWriter -------------------------------------------===//
PPCELFObjectWriter::PPCELFObjectWriter(MCELFObjectTargetWriter *MOTW,

View File

@ -152,7 +152,7 @@ class ELFObjectWriter : public MCObjectWriter {
const MCFragment &F,
const MCFixup &Fixup,
bool IsPCRel) const {
return NULL;
return TargetObjectWriter->ExplicitRelSym(Asm, Target, F, Fixup, IsPCRel);
}
bool is64Bit() const { return TargetObjectWriter->is64Bit(); }
@ -243,8 +243,9 @@ class ELFObjectWriter : public MCObjectWriter {
virtual void WriteHeader(uint64_t SectionDataSize,
unsigned NumberOfSections);
/// Default e_flags = 0
virtual unsigned getEFlags() const { return 0; }
virtual unsigned getEFlags() const {
return TargetObjectWriter->getEFlags();
}
virtual void WriteSymbolEntry(MCDataFragment *SymtabF,
MCDataFragment *ShndxF,
@ -356,35 +357,6 @@ class ELFObjectWriter : public MCObjectWriter {
uint64_t &RelocOffset) {}
};
//===- ARMELFObjectWriter -------------------------------------------===//
class ARMELFObjectWriter : public ELFObjectWriter {
public:
// FIXME: MCAssembler can't yet return the Subtarget,
enum { DefaultEABIVersion = 0x05000000U };
ARMELFObjectWriter(MCELFObjectTargetWriter *MOTW,
raw_ostream &_OS,
bool IsLittleEndian);
virtual ~ARMELFObjectWriter();
virtual unsigned getEFlags() const;
protected:
virtual const MCSymbol *ExplicitRelSym(const MCAssembler &Asm,
const MCValue &Target,
const MCFragment &F,
const MCFixup &Fixup,
bool IsPCRel) const;
virtual unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup,
bool IsPCRel, bool IsRelocWithSymbol,
int64_t Addend) const;
private:
unsigned GetRelocTypeInner(const MCValue &Target,
const MCFixup &Fixup, bool IsPCRel) const;
};
//===- PPCELFObjectWriter -------------------------------------------===//
class PPCELFObjectWriter : public ELFObjectWriter {

View File

@ -19,6 +19,20 @@ MCELFObjectTargetWriter::MCELFObjectTargetWriter(bool Is64Bit_,
HasRelocationAddend(HasRelocationAddend_), Is64Bit(Is64Bit_) {
}
/// Default e_flags = 0
unsigned MCELFObjectTargetWriter::getEFlags() const {
return 0;
}
const MCSymbol *MCELFObjectTargetWriter::ExplicitRelSym(const MCAssembler &Asm,
const MCValue &Target,
const MCFragment &F,
const MCFixup &Fixup,
bool IsPCRel) const {
return NULL;
}
unsigned MCELFObjectTargetWriter::GetRelocType(const MCValue &Target,
const MCFixup &Fixup,
bool IsPCRel,

View File

@ -456,8 +456,7 @@ public:
uint64_t Value) const;
MCObjectWriter *createObjectWriter(raw_ostream &OS) const {
return createELFObjectWriter(new ARMELFObjectWriter(OSABI), OS,
/*IsLittleEndian*/ true);
return createARMELFObjectWriter(OS, OSABI);
}
};

View File

@ -0,0 +1,286 @@
//===-- X86ELFObjectWriter.cpp - X86 ELF Writer ---------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "MCTargetDesc/ARMFixupKinds.h"
#include "MCTargetDesc/ARMMCTargetDesc.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/MC/MCELFObjectWriter.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCSectionELF.h"
#include "llvm/MC/MCValue.h"
using namespace llvm;
namespace {
class ARMELFObjectWriter : public MCELFObjectTargetWriter {
enum { DefaultEABIVersion = 0x05000000U };
const MCSymbol *ExplicitRelSym(const MCAssembler &Asm,
const MCValue &Target,
const MCFragment &F,
const MCFixup &Fixup,
bool IsPCRel) const;
unsigned GetRelocTypeInner(const MCValue &Target,
const MCFixup &Fixup,
bool IsPCRel) const;
public:
ARMELFObjectWriter(uint8_t OSABI);
virtual ~ARMELFObjectWriter();
protected:
virtual unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup,
bool IsPCRel, bool IsRelocWithSymbol,
int64_t Addend) const;
virtual unsigned getEFlags() const;
};
}
ARMELFObjectWriter::ARMELFObjectWriter(uint8_t OSABI)
: MCELFObjectTargetWriter(/*Is64Bit*/ false, OSABI,
ELF::EM_ARM,
/*HasRelocationAddend*/ false) {}
ARMELFObjectWriter::~ARMELFObjectWriter() {}
// FIXME: get the real EABI Version from the Triple.
unsigned ARMELFObjectWriter::getEFlags() const {
return ELF::EF_ARM_EABIMASK & DefaultEABIVersion;
}
// In ARM, _MergedGlobals and other most symbols get emitted directly.
// I.e. not as an offset to a section symbol.
// 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,
const MCFixup &Fixup,
bool IsPCRel) const {
const MCSymbol &Symbol = Target.getSymA()->getSymbol();
bool EmitThisSym = 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 {
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() && 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,
bool IsRelocWithSymbol,
int64_t Addend) const {
return GetRelocTypeInner(Target, Fixup, IsPCRel);
}
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()) {
default: assert(0 && "Unimplemented");
case FK_Data_4:
switch (Modifier) {
default: llvm_unreachable("Unsupported Modifier");
case MCSymbolRefExpr::VK_None:
Type = ELF::R_ARM_REL32;
break;
case MCSymbolRefExpr::VK_ARM_TLSGD:
assert(0 && "unimplemented");
break;
case MCSymbolRefExpr::VK_ARM_GOTTPOFF:
Type = ELF::R_ARM_TLS_IE32;
break;
}
break;
case ARM::fixup_arm_uncondbranch:
switch (Modifier) {
case MCSymbolRefExpr::VK_ARM_PLT:
Type = ELF::R_ARM_PLT32;
break;
default:
Type = ELF::R_ARM_CALL;
break;
}
break;
case ARM::fixup_arm_condbranch:
Type = ELF::R_ARM_JUMP24;
break;
case ARM::fixup_arm_movt_hi16:
case ARM::fixup_arm_movt_hi16_pcrel:
Type = ELF::R_ARM_MOVT_PREL;
break;
case ARM::fixup_arm_movw_lo16:
case ARM::fixup_arm_movw_lo16_pcrel:
Type = ELF::R_ARM_MOVW_PREL_NC;
break;
case ARM::fixup_t2_movt_hi16:
case ARM::fixup_t2_movt_hi16_pcrel:
Type = ELF::R_ARM_THM_MOVT_PREL;
break;
case ARM::fixup_t2_movw_lo16:
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()) {
default: llvm_unreachable("invalid fixup kind!");
case FK_Data_4:
switch (Modifier) {
default: llvm_unreachable("Unsupported Modifier"); break;
case MCSymbolRefExpr::VK_ARM_GOT:
Type = ELF::R_ARM_GOT_BREL;
break;
case MCSymbolRefExpr::VK_ARM_TLSGD:
Type = ELF::R_ARM_TLS_GD32;
break;
case MCSymbolRefExpr::VK_ARM_TPOFF:
Type = ELF::R_ARM_TLS_LE32;
break;
case MCSymbolRefExpr::VK_ARM_GOTTPOFF:
Type = ELF::R_ARM_TLS_IE32;
break;
case MCSymbolRefExpr::VK_None:
Type = ELF::R_ARM_ABS32;
break;
case MCSymbolRefExpr::VK_ARM_GOTOFF:
Type = ELF::R_ARM_GOTOFF32;
break;
}
break;
case ARM::fixup_arm_ldst_pcrel_12:
case ARM::fixup_arm_pcrel_10:
case ARM::fixup_arm_adr_pcrel_12:
case ARM::fixup_arm_thumb_bl:
case ARM::fixup_arm_thumb_cb:
case ARM::fixup_arm_thumb_cp:
case ARM::fixup_arm_thumb_br:
assert(0 && "Unimplemented");
break;
case ARM::fixup_arm_uncondbranch:
Type = ELF::R_ARM_CALL;
break;
case ARM::fixup_arm_condbranch:
Type = ELF::R_ARM_JUMP24;
break;
case ARM::fixup_arm_movt_hi16:
Type = ELF::R_ARM_MOVT_ABS;
break;
case ARM::fixup_arm_movw_lo16:
Type = ELF::R_ARM_MOVW_ABS_NC;
break;
case ARM::fixup_t2_movt_hi16:
Type = ELF::R_ARM_THM_MOVT_ABS;
break;
case ARM::fixup_t2_movw_lo16:
Type = ELF::R_ARM_THM_MOVW_ABS_NC;
break;
}
}
return Type;
}
MCObjectWriter *llvm::createARMELFObjectWriter(raw_ostream &OS,
uint8_t OSABI) {
MCELFObjectTargetWriter *MOTW = new ARMELFObjectWriter(OSABI);
return createELFObjectWriter(MOTW, OS, /*IsLittleEndian=*/true);
}

View File

@ -46,6 +46,10 @@ MCCodeEmitter *createARMMCCodeEmitter(const MCInstrInfo &MCII,
MCAsmBackend *createARMAsmBackend(const Target &T, StringRef TT);
/// createARMELFObjectWriter - Construct an ELF Mach-O object writer.
MCObjectWriter *createARMELFObjectWriter(raw_ostream &OS,
uint8_t OSABI);
/// createARMMachObjectWriter - Construct an ARM Mach-O object writer.
MCObjectWriter *createARMMachObjectWriter(raw_ostream &OS,
bool Is64Bit,