//===----------------------------------------------------------------------===//
#include "llvm/MC/ELFObjectWriter.h"
+#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/Twine.h"
return Type;
}
+static unsigned GetBinding(const MCSymbolData &SD) {
+ uint32_t Binding = (SD.getFlags() & (0xf << ELF_STB_Shift)) >> ELF_STB_Shift;
+ assert(Binding == ELF::STB_LOCAL || Binding == ELF::STB_GLOBAL ||
+ Binding == ELF::STB_WEAK);
+ return Binding;
+}
+
+static void SetBinding(MCSymbolData &SD, unsigned Binding) {
+ assert(Binding == ELF::STB_LOCAL || Binding == ELF::STB_GLOBAL ||
+ Binding == ELF::STB_WEAK);
+ uint32_t OtherFlags = SD.getFlags() & ~(0xf << ELF_STB_Shift);
+ SD.setFlags(OtherFlags | (Binding << ELF_STB_Shift));
+}
+
+static bool isFixupKindX86PCRel(unsigned Kind) {
+ switch (Kind) {
+ default:
+ return false;
+ case X86::reloc_pcrel_1byte:
+ case X86::reloc_pcrel_4byte:
+ case X86::reloc_riprel_4byte:
+ case X86::reloc_riprel_4byte_movq_load:
+ return true;
+ }
+}
+
+static bool RelocNeedsGOT(unsigned Type) {
+ switch (Type) {
+ default:
+ return false;
+ case ELF::R_X86_64_GOT32:
+ case ELF::R_X86_64_PLT32:
+ case ELF::R_X86_64_GOTPCREL:
+ return true;
+ }
+}
+
namespace {
class ELFObjectWriterImpl {
- static bool isFixupKindX86PCRel(unsigned Kind) {
- switch (Kind) {
- default:
- return false;
- case X86::reloc_pcrel_1byte:
- case X86::reloc_pcrel_4byte:
- case X86::reloc_riprel_4byte:
- case X86::reloc_riprel_4byte_movq_load:
- return true;
- }
- }
-
/*static bool isFixupKindX86RIPRel(unsigned Kind) {
return Kind == X86::reloc_riprel_4byte ||
Kind == X86::reloc_riprel_4byte_movq_load;
struct ELFRelocationEntry {
// Make these big enough for both 32-bit and 64-bit
uint64_t r_offset;
- uint64_t r_info;
+ int Index;
+ unsigned Type;
+ const MCSymbol *Symbol;
uint64_t r_addend;
// Support lexicographic sorting.
}
};
+ SmallPtrSet<const MCSymbol *, 16> UsedInReloc;
+
llvm::DenseMap<const MCSectionData*,
std::vector<ELFRelocationEntry> > Relocations;
DenseMap<const MCSection*, uint64_t> SectionStringTableIndex;
/// @}
+ int NumRegularSections;
+
+ bool NeedsGOT;
+
ELFObjectWriter *Writer;
raw_ostream &OS;
public:
ELFObjectWriterImpl(ELFObjectWriter *_Writer, bool _Is64Bit,
bool _HasRelAddend, Triple::OSType _OSType)
- : Writer(_Writer), OS(Writer->getStream()),
+ : NeedsGOT(false), Writer(_Writer), OS(Writer->getStream()),
Is64Bit(_Is64Bit), HasRelocationAddend(_HasRelAddend),
OSType(_OSType) {
}
void CreateMetadataSections(MCAssembler &Asm, MCAsmLayout &Layout);
void ExecutePostLayoutBinding(MCAssembler &Asm) {
- // Compute symbol table information.
- ComputeSymbolTable(Asm);
}
void WriteSecHdrEntry(uint32_t Name, uint32_t Type, uint64_t Flags,
void WriteRelocationsFragment(const MCAssembler &Asm, MCDataFragment *F,
const MCSectionData *SD);
- void WriteObject(const MCAssembler &Asm, const MCAsmLayout &Layout);
+ bool IsFixupFullyResolved(const MCAssembler &Asm,
+ const MCValue Target,
+ bool IsPCRel,
+ const MCFragment *DF) const;
+
+ void WriteObject(MCAssembler &Asm, const MCAsmLayout &Layout);
};
}
}
}
+static uint64_t SymbolValue(MCSymbolData &Data, const MCAsmLayout &Layout) {
+ if (Data.isCommon() && Data.isExternal())
+ return Data.getCommonAlignment();
+
+ const MCSymbol &Symbol = Data.getSymbol();
+ if (!Symbol.isInSection())
+ return 0;
+
+ if (!Data.isCommon() && !(Data.getFlags() & ELF_STB_Weak))
+ if (MCFragment *FF = Data.getFragment())
+ return Layout.getSymbolAddress(&Data) -
+ Layout.getSectionAddress(FF->getParent());
+
+ return 0;
+}
+
void ELFObjectWriterImpl::WriteSymbol(MCDataFragment *F, ELFSymbolData &MSD,
const MCAsmLayout &Layout) {
MCSymbolData &Data = *MSD.SymbolData;
uint8_t Info = (Data.getFlags() & 0xff);
uint8_t Other = ((Data.getFlags() & 0xf00) >> ELF_STV_Shift);
- uint64_t Value = 0;
+ uint64_t Value = SymbolValue(Data, Layout);
uint64_t Size = 0;
const MCExpr *ESize;
- if (Data.isCommon() && Data.isExternal())
- Value = Data.getCommonAlignment();
-
assert(!(Data.isCommon() && !Data.isExternal()));
- if (!Data.isCommon() && !(Data.getFlags() & ELF_STB_Weak))
- if (MCFragment *FF = Data.getFragment())
- Value = Layout.getSymbolAddress(&Data) -
- Layout.getSectionAddress(FF->getParent());
-
ESize = Data.getSize();
if (Data.getSize()) {
MCValue Res;
const MCBinaryExpr *BE = static_cast<const MCBinaryExpr *>(ESize);
if (BE->EvaluateAsRelocatable(Res, &Layout)) {
- MCSymbolData &A =
- Layout.getAssembler().getSymbolData(Res.getSymA()->getSymbol());
- MCSymbolData &B =
- Layout.getAssembler().getSymbolData(Res.getSymB()->getSymbol());
+ uint64_t AddressA = 0;
+ uint64_t AddressB = 0;
+ const MCSymbol &SymA = Res.getSymA()->getSymbol();
+ const MCSymbol &SymB = Res.getSymB()->getSymbol();
+
+ if (SymA.isDefined()) {
+ MCSymbolData &A = Layout.getAssembler().getSymbolData(SymA);
+ AddressA = Layout.getSymbolAddress(&A);
+ }
+
+ if (SymB.isDefined()) {
+ MCSymbolData &B = Layout.getAssembler().getSymbolData(SymB);
+ AddressB = Layout.getSymbolAddress(&B);
+ }
- Size = Layout.getSymbolAddress(&A) - Layout.getSymbolAddress(&B);
+ Size = AddressA - AddressB;
}
} else if (ESize->getKind() == MCExpr::Constant) {
Size = static_cast<const MCConstantExpr *>(ESize)->getValue();
for (unsigned i = 0, e = ExternalSymbolData.size(); i != e; ++i) {
ELFSymbolData &MSD = ExternalSymbolData[i];
MCSymbolData &Data = *MSD.SymbolData;
- assert((Data.getFlags() & ELF_STB_Global) &&
- "External symbol requires STB_GLOBAL flag");
+ assert(((Data.getFlags() & ELF_STB_Global) ||
+ (Data.getFlags() & ELF_STB_Weak)) &&
+ "External symbol requires STB_GLOBAL or STB_WEAK flag");
WriteSymbol(F, MSD, Layout);
- if ((Data.getFlags() & (0xf << ELF_STB_Shift)) == ELF_STB_Local)
+ if (GetBinding(Data) == ELF::STB_LOCAL)
LastLocalSymbolIndex++;
}
for (unsigned i = 0, e = UndefinedSymbolData.size(); i != e; ++i) {
ELFSymbolData &MSD = UndefinedSymbolData[i];
MCSymbolData &Data = *MSD.SymbolData;
- Data.setFlags(Data.getFlags() | ELF_STB_Global);
WriteSymbol(F, MSD, Layout);
- if ((Data.getFlags() & (0xf << ELF_STB_Shift)) == ELF_STB_Local)
+ if (GetBinding(Data) == ELF::STB_LOCAL)
LastLocalSymbolIndex++;
}
}
+static bool ShouldRelocOnSymbol(const MCSymbolData &SD,
+ const MCValue &Target,
+ const MCFragment &F) {
+ const MCSymbol &Symbol = SD.getSymbol();
+ if (Symbol.isUndefined())
+ return true;
+
+ const MCSectionELF &Section =
+ static_cast<const MCSectionELF&>(Symbol.getSection());
+
+ if (SD.isExternal())
+ return true;
+
+ if (Section.getFlags() & MCSectionELF::SHF_MERGE)
+ return Target.getConstant() != 0;
+
+ MCSymbolRefExpr::VariantKind Kind = Target.getSymA()->getKind();
+ const MCSectionELF &Sec2 =
+ static_cast<const MCSectionELF&>(F.getParent()->getSection());
+
+ if (&Sec2 != &Section &&
+ (Kind == MCSymbolRefExpr::VK_PLT || Kind == MCSymbolRefExpr::VK_GOTPCREL))
+ return true;
+
+ return false;
+}
+
// FIXME: this is currently X86/X86_64 only
void ELFObjectWriterImpl::RecordRelocation(const MCAssembler &Asm,
const MCAsmLayout &Layout,
MCValue Target,
uint64_t &FixedValue) {
int64_t Addend = 0;
- unsigned Index = 0;
+ int Index = 0;
int64_t Value = Target.getConstant();
+ const MCSymbol *Symbol = 0;
bool IsPCRel = isFixupKindX86PCRel(Fixup.getKind());
if (!Target.isAbsolute()) {
- const MCSymbol *Symbol = &Target.getSymA()->getSymbol();
+ Symbol = &Target.getSymA()->getSymbol();
MCSymbolData &SD = Asm.getSymbolData(*Symbol);
- const MCSymbolData *Base = Asm.getAtom(Layout, &SD);
MCFragment *F = SD.getFragment();
- // Avoid relocations for cases like jumps and calls in the same file.
+ if (const MCSymbolRefExpr *RefB = Target.getSymB()) {
+ const MCSymbol &SymbolB = RefB->getSymbol();
+ MCSymbolData &SDB = Asm.getSymbolData(SymbolB);
+ IsPCRel = true;
+ MCSectionData *Sec = Fragment->getParent();
+
+ // Offset of the symbol in the section
+ int64_t a = Layout.getSymbolAddress(&SDB) - Layout.getSectionAddress(Sec);
+
+ // Ofeset of the relocation in the section
+ int64_t b = Layout.getFragmentOffset(Fragment) + Fixup.getOffset();
+ Value += b - a;
+ }
+
+ // Check that this case has already been fully resolved before we get
+ // here.
if (Symbol->isDefined() && !SD.isExternal() &&
IsPCRel &&
&Fragment->getParent()->getSection() == &Symbol->getSection()) {
- uint64_t FixupAddr = Layout.getFragmentAddress(Fragment) + Fixup.getOffset();
- FixedValue = Layout.getSymbolAddress(&SD) + Target.getConstant() - FixupAddr;
+ llvm_unreachable("We don't need a relocation in this case.");
return;
}
- if (Base) {
- if (F && (!Symbol->isInSection() || SD.isCommon()) && !SD.isExternal()) {
- Index = F->getParent()->getOrdinal() + LocalSymbolData.size() + 1;
- Value += Layout.getSymbolAddress(&SD);
- } else
- Index = getSymbolIndexInSymbolTable(Asm, Symbol);
- if (Base != &SD)
- Value += Layout.getSymbolAddress(&SD) - Layout.getSymbolAddress(Base);
- Addend = Value;
- // Compensate for the addend on i386.
- if (Is64Bit)
- Value = 0;
+ bool RelocOnSymbol = ShouldRelocOnSymbol(SD, Target, *Fragment);
+ if (!RelocOnSymbol) {
+ Index = F->getParent()->getOrdinal();
+
+ MCSectionData *FSD = F->getParent();
+ // Offset of the symbol in the section
+ Value += Layout.getSymbolAddress(&SD) - Layout.getSectionAddress(FSD);
} else {
- if (F) {
- // Index of the section in .symtab against this symbol
- // is being relocated + 2 (empty section + abs. symbols).
- Index = F->getParent()->getOrdinal() + LocalSymbolData.size() + 1;
-
- MCSectionData *FSD = F->getParent();
- // Offset of the symbol in the section
- Addend = Layout.getSymbolAddress(&SD) - Layout.getSectionAddress(FSD);
- } else {
- FixedValue = Value;
- return;
- }
+ UsedInReloc.insert(Symbol);
+ Index = -1;
}
+ Addend = Value;
+ // Compensate for the addend on i386.
+ if (Is64Bit)
+ Value = 0;
}
FixedValue = Value;
// determine the type of the relocation
+
+ MCSymbolRefExpr::VariantKind Modifier = Target.getSymA()->getKind();
unsigned Type;
if (Is64Bit) {
if (IsPCRel) {
- Type = ELF::R_X86_64_PC32;
+ switch (Modifier) {
+ case MCSymbolRefExpr::VK_None:
+ Type = ELF::R_X86_64_PC32;
+ break;
+ case MCSymbolRefExpr::VK_PLT:
+ Type = ELF::R_X86_64_PLT32;
+ break;
+ case llvm::MCSymbolRefExpr::VK_GOTPCREL:
+ Type = ELF::R_X86_64_GOTPCREL;
+ break;
+ default:
+ llvm_unreachable("Unimplemented");
+ }
} else {
switch ((unsigned)Fixup.getKind()) {
default: llvm_unreachable("invalid fixup kind!");
case FK_Data_8: Type = ELF::R_X86_64_64; break;
+ case X86::reloc_signed_4byte:
case X86::reloc_pcrel_4byte:
- case FK_Data_4:
- // check that the offset fits within a signed long
- if (Target.getConstant() < 0) {
- assert(isInt<32>(Target.getConstant()));
+ assert(isInt<32>(Target.getConstant()));
+ switch (Modifier) {
+ case MCSymbolRefExpr::VK_None:
Type = ELF::R_X86_64_32S;
- } else {
- assert(isUInt<32>(Target.getConstant()));
- Type = ELF::R_X86_64_32;
+ break;
+ case MCSymbolRefExpr::VK_GOT:
+ Type = ELF::R_X86_64_GOT32;
+ break;
+ case llvm::MCSymbolRefExpr::VK_GOTPCREL:
+ Type = ELF::R_X86_64_GOTPCREL;
+ break;
+ default:
+ llvm_unreachable("Unimplemented");
}
break;
+ case FK_Data_4:
+ Type = ELF::R_X86_64_32;
+ break;
case FK_Data_2: Type = ELF::R_X86_64_16; break;
case X86::reloc_pcrel_1byte:
case FK_Data_1: Type = ELF::R_X86_64_8; break;
} else {
switch ((unsigned)Fixup.getKind()) {
default: llvm_unreachable("invalid fixup kind!");
+
+ // FIXME: Should we avoid selecting reloc_signed_4byte in 32 bit mode
+ // instead?
+ case X86::reloc_signed_4byte:
case X86::reloc_pcrel_4byte:
case FK_Data_4: Type = ELF::R_386_32; break;
case FK_Data_2: Type = ELF::R_386_16; break;
}
}
+ if (RelocNeedsGOT(Type))
+ NeedsGOT = true;
+
ELFRelocationEntry ERE;
- if (Is64Bit) {
- struct ELF::Elf64_Rela ERE64;
- ERE64.setSymbolAndType(Index, Type);
- ERE.r_info = ERE64.r_info;
- } else {
- struct ELF::Elf32_Rela ERE32;
- ERE32.setSymbolAndType(Index, Type);
- ERE.r_info = ERE32.r_info;
- }
+ ERE.Index = Index;
+ ERE.Type = Type;
+ ERE.Symbol = Symbol;
ERE.r_offset = Layout.getFragmentOffset(Fragment) + Fixup.getOffset();
return SD.getIndex() + /* empty symbol */ 1;
// External or undefined symbol.
- return SD.getIndex() + Asm.size() + /* empty symbol */ 1;
+ return SD.getIndex() + NumRegularSections + /* empty symbol */ 1;
+}
+
+static bool isInSymtab(const MCAssembler &Asm, const MCSymbolData &Data,
+ bool Used) {
+ const MCSymbol &Symbol = Data.getSymbol();
+ if (!Asm.isSymbolLinkerVisible(Symbol) && !Symbol.isUndefined())
+ return false;
+
+ if (!Used && Symbol.isTemporary())
+ return false;
+
+ return true;
+}
+
+static bool isLocal(const MCSymbolData &Data) {
+ if (Data.isExternal())
+ return false;
+
+ const MCSymbol &Symbol = Data.getSymbol();
+ if (Symbol.isUndefined() && !Symbol.isVariable())
+ return false;
+
+ return true;
}
void ELFObjectWriterImpl::ComputeSymbolTable(MCAssembler &Asm) {
+ // FIXME: Is this the correct place to do this?
+ if (NeedsGOT) {
+ llvm::StringRef Name = "_GLOBAL_OFFSET_TABLE_";
+ MCSymbol *Sym = Asm.getContext().GetOrCreateSymbol(Name);
+ MCSymbolData &Data = Asm.getOrCreateSymbolData(*Sym);
+ Data.setExternal(true);
+ }
+
// Build section lookup table.
- DenseMap<const MCSection*, uint8_t> SectionIndexMap;
+ NumRegularSections = Asm.size();
+ DenseMap<const MCSection*, uint32_t> SectionIndexMap;
unsigned Index = 1;
for (MCAssembler::iterator it = Asm.begin(),
ie = Asm.end(); it != ie; ++it, ++Index)
ie = Asm.symbol_end(); it != ie; ++it) {
const MCSymbol &Symbol = it->getSymbol();
- // Ignore non-linker visible symbols.
- if (!Asm.isSymbolLinkerVisible(Symbol))
+ if (!isInSymtab(Asm, *it, UsedInReloc.count(&Symbol)))
continue;
- if (it->isExternal() || Symbol.isUndefined())
+ if (!isLocal(*it))
continue;
uint64_t &Entry = StringIndexMap[Symbol.getName()];
MSD.SectionIndex = ELF::SHN_ABS;
LocalSymbolData.push_back(MSD);
} else {
- MSD.SectionIndex = SectionIndexMap.lookup(&Symbol.getSection());
+ const MCSymbol *SymbolP = &Symbol;
+ if (Symbol.isVariable()) {
+ const MCExpr *Value = Symbol.getVariableValue();
+ assert (Value->getKind() == MCExpr::SymbolRef && "Unimplemented");
+ const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr*>(Value);
+ SymbolP = &Ref->getSymbol();
+ }
+ MSD.SectionIndex = SectionIndexMap.lookup(&SymbolP->getSection());
assert(MSD.SectionIndex && "Invalid section index!");
LocalSymbolData.push_back(MSD);
}
ie = Asm.symbol_end(); it != ie; ++it) {
const MCSymbol &Symbol = it->getSymbol();
- // Ignore non-linker visible symbols.
- if (!Asm.isSymbolLinkerVisible(Symbol))
+ if (!isInSymtab(Asm, *it, UsedInReloc.count(&Symbol)))
continue;
- if (!it->isExternal() && !Symbol.isUndefined())
+ if (isLocal(*it))
continue;
uint64_t &Entry = StringIndexMap[Symbol.getName()];
MSD.SymbolData = it;
MSD.StringIndex = Entry;
+ // FIXME: There is duplicated code with the local case.
if (it->isCommon()) {
MSD.SectionIndex = ELF::SHN_COMMON;
ExternalSymbolData.push_back(MSD);
+ } else if (Symbol.isVariable()) {
+ const MCExpr *Value = Symbol.getVariableValue();
+ assert (Value->getKind() == MCExpr::SymbolRef && "Unimplemented");
+ const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr*>(Value);
+ const MCSymbol &RefSymbol = Ref->getSymbol();
+ if (RefSymbol.isDefined()) {
+ MSD.SectionIndex = SectionIndexMap.lookup(&RefSymbol.getSection());
+ assert(MSD.SectionIndex && "Invalid section index!");
+ ExternalSymbolData.push_back(MSD);
+ }
} else if (Symbol.isUndefined()) {
MSD.SectionIndex = ELF::SHN_UNDEF;
- // XXX: for some reason we dont Emit* this
- it->setFlags(it->getFlags() | ELF_STB_Global);
+ // FIXME: Undefined symbols are global, but this is the first place we
+ // are able to set it.
+ if (GetBinding(*it) == ELF::STB_LOCAL)
+ SetBinding(*it, ELF::STB_GLOBAL);
UndefinedSymbolData.push_back(MSD);
} else if (Symbol.isAbsolute()) {
MSD.SectionIndex = ELF::SHN_ABS;
WriteRelocationsFragment(Asm, F, &SD);
- Asm.AddSectionToTheEnd(RelaSD, Layout);
+ Asm.AddSectionToTheEnd(*Writer, RelaSD, Layout);
}
}
for (unsigned i = 0, e = Relocs.size(); i != e; ++i) {
ELFRelocationEntry entry = Relocs[e - i - 1];
+ if (entry.Index < 0)
+ entry.Index = getSymbolIndexInSymbolTable(Asm, entry.Symbol);
+ else
+ entry.Index += LocalSymbolData.size() + 1;
if (Is64Bit) {
char buf[8];
String64(buf, entry.r_offset);
F->getContents() += StringRef(buf, 8);
- String64(buf, entry.r_info);
+ struct ELF::Elf64_Rela ERE64;
+ ERE64.setSymbolAndType(entry.Index, entry.Type);
+ String64(buf, ERE64.r_info);
F->getContents() += StringRef(buf, 8);
if (HasRelocationAddend) {
String32(buf, entry.r_offset);
F->getContents() += StringRef(buf, 4);
- String32(buf, entry.r_info);
+ struct ELF::Elf32_Rela ERE32;
+ ERE32.setSymbolAndType(entry.Index, entry.Type);
+ String32(buf, ERE32.r_info);
F->getContents() += StringRef(buf, 4);
if (HasRelocationAddend) {
MCContext &Ctx = Asm.getContext();
MCDataFragment *F;
- WriteRelocations(Asm, Layout);
-
const MCSection *SymtabSection;
unsigned EntrySize = Is64Bit ? ELF::SYMENTRY_SIZE64 : ELF::SYMENTRY_SIZE32;
StrtabSD.setAlignment(1);
StringTableIndex = Asm.size();
+ WriteRelocations(Asm, Layout);
// Symbol table
F = new MCDataFragment(&SymtabSD);
WriteSymbolTable(F, Asm, Layout, NumRegularSections);
- Asm.AddSectionToTheEnd(SymtabSD, Layout);
+ Asm.AddSectionToTheEnd(*Writer, SymtabSD, Layout);
F = new MCDataFragment(&StrtabSD);
F->getContents().append(StringTable.begin(), StringTable.end());
- Asm.AddSectionToTheEnd(StrtabSD, Layout);
+ Asm.AddSectionToTheEnd(*Writer, StrtabSD, Layout);
F = new MCDataFragment(&ShstrtabSD);
F->getContents() += '\x00';
}
- Asm.AddSectionToTheEnd(ShstrtabSD, Layout);
+ Asm.AddSectionToTheEnd(*Writer, ShstrtabSD, Layout);
+}
+
+bool ELFObjectWriterImpl::IsFixupFullyResolved(const MCAssembler &Asm,
+ const MCValue Target,
+ bool IsPCRel,
+ const MCFragment *DF) const {
+ // If this is a PCrel relocation, find the section this fixup value is
+ // relative to.
+ const MCSection *BaseSection = 0;
+ if (IsPCRel) {
+ BaseSection = &DF->getParent()->getSection();
+ assert(BaseSection);
+ }
+
+ const MCSection *SectionA = 0;
+ const MCSymbol *SymbolA = 0;
+ if (const MCSymbolRefExpr *A = Target.getSymA()) {
+ SymbolA = &A->getSymbol();
+ SectionA = &SymbolA->getSection();
+ }
+
+ const MCSection *SectionB = 0;
+ if (const MCSymbolRefExpr *B = Target.getSymB()) {
+ SectionB = &B->getSymbol().getSection();
+ }
+
+ if (!BaseSection)
+ return SectionA == SectionB;
+
+ const MCSymbolData &DataA = Asm.getSymbolData(*SymbolA);
+ if (DataA.isExternal())
+ return false;
+
+ return !SectionB && BaseSection == SectionA;
}
-void ELFObjectWriterImpl::WriteObject(const MCAssembler &Asm,
+void ELFObjectWriterImpl::WriteObject(MCAssembler &Asm,
const MCAsmLayout &Layout) {
+ // Compute symbol table information.
+ ComputeSymbolTable(Asm);
+
CreateMetadataSections(const_cast<MCAssembler&>(Asm),
const_cast<MCAsmLayout&>(Layout));
Target, FixedValue);
}
-void ELFObjectWriter::WriteObject(const MCAssembler &Asm,
+bool ELFObjectWriter::IsFixupFullyResolved(const MCAssembler &Asm,
+ const MCValue Target,
+ bool IsPCRel,
+ const MCFragment *DF) const {
+ return ((ELFObjectWriterImpl*) Impl)->IsFixupFullyResolved(Asm, Target,
+ IsPCRel, DF);
+}
+
+void ELFObjectWriter::WriteObject(MCAssembler &Asm,
const MCAsmLayout &Layout) {
((ELFObjectWriterImpl*) Impl)->WriteObject(Asm, Layout);
}