X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FMC%2FWinCOFFObjectWriter.cpp;h=b15e225fc2a318de11bb98ddf5542bd1f33ab00d;hb=b6777eae58392cb5e19282622996e81c72b72a3e;hp=82ccddf81d98afa292bc68d3530a15eecfec3c4c;hpb=a8c02c3bdd68e65d14fb6b0d56989663754059b0;p=oota-llvm.git diff --git a/lib/MC/WinCOFFObjectWriter.cpp b/lib/MC/WinCOFFObjectWriter.cpp index 82ccddf81d9..b15e225fc2a 100644 --- a/lib/MC/WinCOFFObjectWriter.cpp +++ b/lib/MC/WinCOFFObjectWriter.cpp @@ -31,9 +31,9 @@ #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" -#include "llvm/System/TimeValue.h" +#include "llvm/Support/TimeValue.h" -#include "../Target/X86/X86FixupKinds.h" +#include "../Target/X86/MCTargetDesc/X86FixupKinds.h" #include @@ -125,11 +125,8 @@ public: typedef std::vector symbols; typedef std::vector sections; - typedef StringMap name_symbol_map; - typedef StringMap name_section_map; - - typedef DenseMap symbol_map; - typedef DenseMap section_map; + typedef DenseMap symbol_map; + typedef DenseMap section_map; // Root level file contents. bool Is64Bit; @@ -145,8 +142,9 @@ public: WinCOFFObjectWriter(raw_ostream &OS, bool is64Bit); ~WinCOFFObjectWriter(); - COFFSymbol *createSymbol(llvm::StringRef Name); - COFFSection *createSection(llvm::StringRef Name); + COFFSymbol *createSymbol(StringRef Name); + COFFSymbol *GetOrCreateCOFFSymbol(const MCSymbol * Symbol); + COFFSection *createSection(StringRef Name); template object_t *createCOFFEntity(llvm::StringRef Name, list_t &List); @@ -172,7 +170,7 @@ public: // MCObjectWriter interface implementation. - void ExecutePostLayoutBinding(MCAssembler &Asm); + void ExecutePostLayoutBinding(MCAssembler &Asm, const MCAsmLayout &Layout); void RecordRelocation(const MCAssembler &Asm, const MCAsmLayout &Layout, @@ -181,12 +179,7 @@ public: MCValue Target, uint64_t &FixedValue); - virtual bool IsFixupFullyResolved(const MCAssembler &Asm, - const MCValue Target, - bool IsPCRel, - const MCFragment *DF) const; - - void WriteObject(const MCAssembler &Asm, const MCAsmLayout &Layout); + void WriteObject(MCAssembler &Asm, const MCAsmLayout &Layout); }; } @@ -336,10 +329,20 @@ WinCOFFObjectWriter::~WinCOFFObjectWriter() { delete *I; } -COFFSymbol *WinCOFFObjectWriter::createSymbol(llvm::StringRef Name) { +COFFSymbol *WinCOFFObjectWriter::createSymbol(StringRef Name) { return createCOFFEntity(Name, Symbols); } +COFFSymbol *WinCOFFObjectWriter::GetOrCreateCOFFSymbol(const MCSymbol * Symbol){ + symbol_map::iterator i = SymbolMap.find(Symbol); + if (i != SymbolMap.end()) + return i->second; + COFFSymbol *RetSymbol + = createCOFFEntity(Symbol->getName(), Symbols); + SymbolMap[Symbol] = RetSymbol; + return RetSymbol; +} + COFFSection *WinCOFFObjectWriter::createSection(llvm::StringRef Name) { return createCOFFEntity(Name, Sections); } @@ -359,6 +362,8 @@ object_t *WinCOFFObjectWriter::createCOFFEntity(llvm::StringRef Name, /// This function takes a section data object from the assembler /// and creates the associated COFF section staging object. void WinCOFFObjectWriter::DefineSection(MCSectionData const &SectionData) { + assert(SectionData.getSection().getVariant() == MCSection::SV_COFF + && "Got non COFF section in the COFF backend!"); // FIXME: Not sure how to verify this (at least in a debug build). MCSectionCOFF const &Sec = static_cast(SectionData.getSection()); @@ -400,48 +405,43 @@ void WinCOFFObjectWriter::DefineSection(MCSectionData const &SectionData) { // Bind internal COFF section to MC section. coff_section->MCData = &SectionData; - SectionMap[&SectionData] = coff_section; + SectionMap[&SectionData.getSection()] = coff_section; } /// This function takes a section data object from the assembler /// and creates the associated COFF symbol staging object. void WinCOFFObjectWriter::DefineSymbol(MCSymbolData const &SymbolData, MCAssembler &Assembler) { - assert(!SymbolData.getSymbol().isVariable() - && "Cannot define a symbol that is a variable!"); - COFFSymbol *coff_symbol = createSymbol(SymbolData.getSymbol().getName()); + COFFSymbol *coff_symbol = GetOrCreateCOFFSymbol(&SymbolData.getSymbol()); coff_symbol->Data.Type = (SymbolData.getFlags() & 0x0000FFFF) >> 0; coff_symbol->Data.StorageClass = (SymbolData.getFlags() & 0x00FF0000) >> 16; - // If no storage class was specified in the streamer, define it here. - if (coff_symbol->Data.StorageClass == 0) { - bool external = SymbolData.isExternal() || (SymbolData.Fragment == NULL); - - coff_symbol->Data.StorageClass = - external ? COFF::IMAGE_SYM_CLASS_EXTERNAL : COFF::IMAGE_SYM_CLASS_STATIC; - } - - if (SymbolData.getFlags() & COFF::SF_WeakReference) { + if (SymbolData.getFlags() & COFF::SF_WeakExternal) { coff_symbol->Data.StorageClass = COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL; - const MCExpr *Value = SymbolData.getSymbol().getVariableValue(); - - // FIXME: This assert message isn't very good. - assert(Value->getKind() == MCExpr::SymbolRef && - "Value must be a SymbolRef!"); - - const MCSymbolRefExpr *SymbolRef = - static_cast(Value); - - const MCSymbolData &OtherSymbolData = - Assembler.getSymbolData(SymbolRef->getSymbol()); + if (SymbolData.getSymbol().isVariable()) { + coff_symbol->Data.StorageClass = COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL; + const MCExpr *Value = SymbolData.getSymbol().getVariableValue(); - // FIXME: This assert message isn't very good. - assert(SymbolMap.find(&OtherSymbolData) != SymbolMap.end() && - "OtherSymbolData must be in the symbol map!"); + // FIXME: This assert message isn't very good. + assert(Value->getKind() == MCExpr::SymbolRef && + "Value must be a SymbolRef!"); - coff_symbol->Other = SymbolMap[&OtherSymbolData]; + const MCSymbolRefExpr *SymbolRef = + static_cast(Value); + coff_symbol->Other = GetOrCreateCOFFSymbol(&SymbolRef->getSymbol()); + } else { + std::string WeakName = std::string(".weak.") + + SymbolData.getSymbol().getName().str() + + ".default"; + COFFSymbol *WeakDefault = createSymbol(WeakName); + WeakDefault->Data.SectionNumber = COFF::IMAGE_SYM_ABSOLUTE; + WeakDefault->Data.StorageClass = COFF::IMAGE_SYM_CLASS_EXTERNAL; + WeakDefault->Data.Type = 0; + WeakDefault->Data.Value = 0; + coff_symbol->Other = WeakDefault; + } // Setup the Weak External auxiliary symbol. coff_symbol->Aux.resize(1); @@ -449,15 +449,24 @@ void WinCOFFObjectWriter::DefineSymbol(MCSymbolData const &SymbolData, coff_symbol->Aux[0].AuxType = ATWeakExternal; coff_symbol->Aux[0].Aux.WeakExternal.TagIndex = 0; coff_symbol->Aux[0].Aux.WeakExternal.Characteristics = - COFF::IMAGE_WEAK_EXTERN_SEARCH_LIBRARY; + COFF::IMAGE_WEAK_EXTERN_SEARCH_LIBRARY; + } + + // If no storage class was specified in the streamer, define it here. + if (coff_symbol->Data.StorageClass == 0) { + bool external = SymbolData.isExternal() || (SymbolData.Fragment == NULL); + + coff_symbol->Data.StorageClass = + external ? COFF::IMAGE_SYM_CLASS_EXTERNAL : COFF::IMAGE_SYM_CLASS_STATIC; } if (SymbolData.Fragment != NULL) - coff_symbol->Section = SectionMap[SymbolData.Fragment->getParent()]; + coff_symbol->Section = + SectionMap[&SymbolData.Fragment->getParent()->getSection()]; // Bind internal COFF symbol to MC symbol. coff_symbol->MCData = &SymbolData; - SymbolMap[&SymbolData] = coff_symbol; + SymbolMap[&SymbolData.getSymbol()] = coff_symbol; } /// making a section real involves assigned it a number and putting @@ -507,7 +516,7 @@ bool WinCOFFObjectWriter::ExportSymbol(MCSymbolData const &SymbolData, // For now, all non-variable symbols are exported, // the linker will sort the rest out for us. - return !SymbolData.getSymbol().isVariable(); + return SymbolData.isExternal() || !SymbolData.getSymbol().isVariable(); } bool WinCOFFObjectWriter::IsPhysicalSection(COFFSection *S) { @@ -602,7 +611,8 @@ void WinCOFFObjectWriter::WriteRelocation(const COFF::relocation &R) { //////////////////////////////////////////////////////////////////////////////// // MCObjectWriter interface implementations -void WinCOFFObjectWriter::ExecutePostLayoutBinding(MCAssembler &Asm) { +void WinCOFFObjectWriter::ExecutePostLayoutBinding(MCAssembler &Asm, + const MCAsmLayout &Layout) { // "Define" each section & symbol. This creates section & symbol // entries in the staging area. @@ -630,24 +640,34 @@ void WinCOFFObjectWriter::RecordRelocation(const MCAssembler &Asm, MCSectionData const *SectionData = Fragment->getParent(); // Mark this symbol as requiring an entry in the symbol table. - assert(SectionMap.find(SectionData) != SectionMap.end() && + assert(SectionMap.find(&SectionData->getSection()) != SectionMap.end() && "Section must already have been defined in ExecutePostLayoutBinding!"); - assert(SymbolMap.find(&A_SD) != SymbolMap.end() && + assert(SymbolMap.find(&A_SD.getSymbol()) != SymbolMap.end() && "Symbol must already have been defined in ExecutePostLayoutBinding!"); - COFFSection *coff_section = SectionMap[SectionData]; - COFFSymbol *coff_symbol = SymbolMap[&A_SD]; + COFFSection *coff_section = SectionMap[&SectionData->getSection()]; + COFFSymbol *coff_symbol = SymbolMap[&A_SD.getSymbol()]; + const MCSymbolRefExpr *SymA = Target.getSymA(); + const MCSymbolRefExpr *SymB = Target.getSymB(); + const bool CrossSection = SymB && + &SymA->getSymbol().getSection() != &SymB->getSymbol().getSection(); if (Target.getSymB()) { const MCSymbol *B = &Target.getSymB()->getSymbol(); MCSymbolData &B_SD = Asm.getSymbolData(*B); - FixedValue = Layout.getSymbolAddress(&A_SD) - Layout.getSymbolAddress(&B_SD); + // Offset of the symbol in the section + int64_t a = Layout.getSymbolOffset(&B_SD); + // Ofeset of the relocation in the section + int64_t b = Layout.getFragmentOffset(Fragment) + Fixup.getOffset(); + + FixedValue = b - a; // In the case where we have SymbA and SymB, we just need to store the delta // between the two symbols. Update FixedValue to account for the delta, and // skip recording the relocation. - return; + if (!CrossSection) + return; } else { FixedValue = Target.getConstant(); } @@ -657,10 +677,11 @@ void WinCOFFObjectWriter::RecordRelocation(const MCAssembler &Asm, Reloc.Data.SymbolTableIndex = 0; Reloc.Data.VirtualAddress = Layout.getFragmentOffset(Fragment); - // turn relocations for temporary symbols into section relocations - if (coff_symbol->MCData->getSymbol().isTemporary()) { + // Turn relocations for temporary symbols into section relocations. + if (coff_symbol->MCData->getSymbol().isTemporary() || CrossSection) { Reloc.Symb = coff_symbol->Section->Symbol; - FixedValue += Layout.getFragmentOffset(coff_symbol->MCData->Fragment); + FixedValue += Layout.getFragmentOffset(coff_symbol->MCData->Fragment) + + coff_symbol->MCData->getOffset(); } else Reloc.Symb = coff_symbol; @@ -668,8 +689,13 @@ void WinCOFFObjectWriter::RecordRelocation(const MCAssembler &Asm, Reloc.Data.VirtualAddress += Fixup.getOffset(); - switch (Fixup.getKind()) { - case X86::reloc_pcrel_4byte: + unsigned FixupKind = Fixup.getKind(); + + if (CrossSection) + FixupKind = FK_PCRel_4; + + switch (FixupKind) { + case FK_PCRel_4: case X86::reloc_riprel_4byte: case X86::reloc_riprel_4byte_movq_load: Reloc.Data.Type = Is64Bit ? COFF::IMAGE_REL_AMD64_REL32 @@ -696,21 +722,14 @@ void WinCOFFObjectWriter::RecordRelocation(const MCAssembler &Asm, coff_section->Relocations.push_back(Reloc); } -bool WinCOFFObjectWriter::IsFixupFullyResolved(const MCAssembler &Asm, - const MCValue Target, - bool IsPCRel, - const MCFragment *DF) const { - return false; -} - -void WinCOFFObjectWriter::WriteObject(const MCAssembler &Asm, +void WinCOFFObjectWriter::WriteObject(MCAssembler &Asm, const MCAsmLayout &Layout) { // Assign symbol and section indexes and offsets. Header.NumberOfSections = 0; for (sections::iterator i = Sections.begin(), e = Sections.end(); i != e; i++) { - if (Layout.getSectionSize((*i)->MCData) > 0) { + if (Layout.getSectionAddressSize((*i)->MCData) > 0) { MakeSectionReal(**i, ++Header.NumberOfSections); } else { (*i)->Number = -1; @@ -765,12 +784,12 @@ void WinCOFFObjectWriter::WriteObject(const MCAssembler &Asm, for (MCAssembler::const_iterator i = Asm.begin(), e = Asm.end(); i != e; i++) { - COFFSection *Sec = SectionMap[i]; + COFFSection *Sec = SectionMap[&i->getSection()]; if (Sec->Number == -1) continue; - Sec->Header.SizeOfRawData = Layout.getSectionFileSize(i); + Sec->Header.SizeOfRawData = Layout.getSectionAddressSize(i); if (IsPhysicalSection(Sec)) { Sec->Header.PointerToRawData = offset; @@ -830,7 +849,7 @@ void WinCOFFObjectWriter::WriteObject(const MCAssembler &Asm, assert(OS.tell() == (*i)->Header.PointerToRawData && "Section::PointerToRawData is insane!"); - Asm.WriteSectionData(j, Layout, this); + Asm.WriteSectionData(j, Layout); } if ((*i)->Relocations.size() > 0) {