X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FCodeGen%2FELFWriter.cpp;h=3e1645b2c341ef54b2dd29d6d642c79218662412;hb=a4ff5e48fc6a4718d3a2af8654cfc06a17310aed;hp=ddc3670665d69a96b9c2a3d2f67c645ac22154b2;hpb=6933d3eff8e47a64803ece18b5a78748a674dc43;p=oota-llvm.git diff --git a/lib/CodeGen/ELFWriter.cpp b/lib/CodeGen/ELFWriter.cpp index ddc3670665d..3e1645b2c34 100644 --- a/lib/CodeGen/ELFWriter.cpp +++ b/lib/CodeGen/ELFWriter.cpp @@ -51,6 +51,7 @@ #include "llvm/Support/Streams.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" using namespace llvm; @@ -144,10 +145,11 @@ bool ELFWriter::doInitialization(Module &M) { return false; } +// getGlobalELFVisibility - Returns the ELF specific visibility type unsigned ELFWriter::getGlobalELFVisibility(const GlobalValue *GV) { switch (GV->getVisibility()) { default: - assert(0 && "unknown visibility type"); + llvm_unreachable("unknown visibility type"); case GlobalValue::DefaultVisibility: return ELFSym::STV_DEFAULT; case GlobalValue::HiddenVisibility: @@ -155,11 +157,11 @@ unsigned ELFWriter::getGlobalELFVisibility(const GlobalValue *GV) { case GlobalValue::ProtectedVisibility: return ELFSym::STV_PROTECTED; } - return 0; } -unsigned ELFWriter::getGlobalELFLinkage(const GlobalValue *GV) { +// getGlobalELFBinding - Returns the ELF specific binding type +unsigned ELFWriter::getGlobalELFBinding(const GlobalValue *GV) { if (GV->hasInternalLinkage()) return ELFSym::STB_LOCAL; @@ -169,8 +171,19 @@ unsigned ELFWriter::getGlobalELFLinkage(const GlobalValue *GV) { return ELFSym::STB_GLOBAL; } -// getElfSectionFlags - Get the ELF Section Header based on the -// flags defined in ELFTargetAsmInfo. +// getGlobalELFType - Returns the ELF specific type for a global +unsigned ELFWriter::getGlobalELFType(const GlobalValue *GV) { + if (GV->isDeclaration()) + return ELFSym::STT_NOTYPE; + + if (isa(GV)) + return ELFSym::STT_FUNC; + + return ELFSym::STT_OBJECT; +} + +// getElfSectionFlags - Get the ELF Section Header flags based +// on the flags defined in ELFTargetAsmInfo. unsigned ELFWriter::getElfSectionFlags(unsigned Flags) { unsigned ElfSectionFlags = ELFSection::SHF_ALLOC; @@ -188,101 +201,103 @@ unsigned ELFWriter::getElfSectionFlags(unsigned Flags) { return ElfSectionFlags; } -// For global symbols without a section, return the Null section as a -// placeholder -ELFSection &ELFWriter::getGlobalSymELFSection(const GlobalVariable *GV, - ELFSym &Sym) { - // If this is a declaration, the symbol does not have a section. - if (!GV->hasInitializer()) { - Sym.SectionIdx = ELFSection::SHN_UNDEF; - return getNullSection(); - } - - // Get the name and flags of the section for the global - const Section *S = TAI->SectionForGlobal(GV); - unsigned SectionType = ELFSection::SHT_PROGBITS; - unsigned SectionFlags = getElfSectionFlags(S->getFlags()); - DOUT << "Section " << S->getName() << " for global " << GV->getName() << "\n"; +// isELFUndefSym - the symbol has no section and must be placed in +// the symbol table with a reference to the null section. +static bool isELFUndefSym(const GlobalValue *GV) { + return GV->isDeclaration(); +} - const TargetData *TD = TM.getTargetData(); - unsigned Align = TD->getPreferredAlignment(GV); - Constant *CV = GV->getInitializer(); - - // If this global has a zero initializer, go to .bss or common section. - // Variables are part of the common block if they are zero initialized - // and allowed to be merged with other symbols. - if (CV->isNullValue() || isa(CV)) { - SectionType = ELFSection::SHT_NOBITS; - ELFSection &ElfS = getSection(S->getName(), SectionType, SectionFlags); - if (GV->hasLinkOnceLinkage() || GV->hasWeakLinkage() || - GV->hasCommonLinkage()) { - Sym.SectionIdx = ELFSection::SHN_COMMON; - Sym.IsCommon = true; - ElfS.Align = 1; - return ElfS; - } - Sym.IsBss = true; - Sym.SectionIdx = ElfS.SectionIdx; - if (Align) ElfS.Size = (ElfS.Size + Align-1) & ~(Align-1); - ElfS.Align = std::max(ElfS.Align, Align); - return ElfS; - } +// isELFBssSym - for an undef or null value, the symbol must go to a bss +// section if it's not weak for linker, otherwise it's a common sym. +static bool isELFBssSym(const GlobalValue *GV) { + return (!GV->isDeclaration() && + (GV->isNullValue() || isa(GV)) && + !GV->isWeakForLinker()); +} - Sym.IsConstant = true; - ELFSection &ElfS = getSection(S->getName(), SectionType, SectionFlags); - Sym.SectionIdx = ElfS.SectionIdx; - ElfS.Align = std::max(ElfS.Align, Align); - return ElfS; +// isELFCommonSym - for an undef or null value, the symbol must go to a +// common section if it's weak for linker, otherwise bss. +static bool isELFCommonSym(const GlobalValue *GV) { + return (!GV->isDeclaration() && + (GV->isNullValue() || isa(GV)) + && GV->isWeakForLinker()); } -void ELFWriter::EmitFunctionDeclaration(const Function *F) { - ELFSym GblSym(F); - GblSym.setBind(ELFSym::STB_GLOBAL); - GblSym.setType(ELFSym::STT_NOTYPE); - GblSym.setVisibility(ELFSym::STV_DEFAULT); - GblSym.SectionIdx = ELFSection::SHN_UNDEF; - SymbolList.push_back(GblSym); +// isELFDataSym - if the symbol is an initialized but no null constant +// it must go to some kind of data section gathered from TAI +static bool isELFDataSym(const GlobalValue *GV) { + return (!GV->isDeclaration() && + !(GV->isNullValue() || isa(GV))); } -void ELFWriter::EmitGlobalVar(const GlobalVariable *GV) { - unsigned SymBind = getGlobalELFLinkage(GV); - unsigned Align=0, Size=0; - ELFSym GblSym(GV); - GblSym.setBind(SymBind); - GblSym.setVisibility(getGlobalELFVisibility(GV)); +// EmitGlobal - Choose the right section for global and emit it +void ELFWriter::EmitGlobal(const GlobalValue *GV) { - if (GV->hasInitializer()) { - GblSym.setType(ELFSym::STT_OBJECT); - const TargetData *TD = TM.getTargetData(); - Align = TD->getPreferredAlignment(GV); - Size = TD->getTypeAllocSize(GV->getInitializer()->getType()); - GblSym.Size = Size; + // Handle ELF Bind, Visibility and Type for the current symbol + unsigned SymBind = getGlobalELFBinding(GV); + ELFSym *GblSym = new ELFSym(GV); + GblSym->setBind(SymBind); + GblSym->setVisibility(getGlobalELFVisibility(GV)); + GblSym->setType(getGlobalELFType(GV)); + + if (isELFUndefSym(GV)) { + GblSym->SectionIdx = ELFSection::SHN_UNDEF; } else { - GblSym.setType(ELFSym::STT_NOTYPE); - } + assert(isa(GV) && "GV not a global variable!"); + const GlobalVariable *GVar = dyn_cast(GV); - ELFSection &GblSection = getGlobalSymELFSection(GV, GblSym); - - if (GblSym.IsCommon) { - GblSym.Value = Align; - } else if (GblSym.IsBss) { - GblSym.Value = GblSection.Size; - GblSection.Size += Size; - } else if (GblSym.IsConstant){ - // GblSym.Value should contain the symbol index inside the section, - // and all symbols should start on their required alignment boundary - GblSym.Value = (GblSection.size() + (Align-1)) & (-Align); - GblSection.emitAlignment(Align); - EmitGlobalConstant(GV->getInitializer(), GblSection); - } + // Get ELF section from TAI + const Section *S = TAI->SectionForGlobal(GV); + unsigned SectionFlags = getElfSectionFlags(S->getFlags()); - // Local symbols should come first on the symbol table. - if (!GV->hasPrivateLinkage()) { - if (SymBind == ELFSym::STB_LOCAL) - SymbolList.push_front(GblSym); - else - SymbolList.push_back(GblSym); + // The symbol align should update the section alignment if needed + const TargetData *TD = TM.getTargetData(); + unsigned Align = TD->getPreferredAlignment(GVar); + unsigned Size = TD->getTypeAllocSize(GVar->getInitializer()->getType()); + GblSym->Size = Size; + + if (isELFCommonSym(GV)) { + GblSym->SectionIdx = ELFSection::SHN_COMMON; + getSection(S->getName(), ELFSection::SHT_NOBITS, SectionFlags, 1); + + // A new linkonce section is created for each global in the + // common section, the default alignment is 1 and the symbol + // value contains its alignment. + GblSym->Value = Align; + + } else if (isELFBssSym(GV)) { + ELFSection &ES = + getSection(S->getName(), ELFSection::SHT_NOBITS, SectionFlags); + GblSym->SectionIdx = ES.SectionIdx; + + // Update the size with alignment and the next object can + // start in the right offset in the section + if (Align) ES.Size = (ES.Size + Align-1) & ~(Align-1); + ES.Align = std::max(ES.Align, Align); + + // GblSym->Value should contain the virtual offset inside the section. + // Virtual because the BSS space is not allocated on ELF objects + GblSym->Value = ES.Size; + ES.Size += Size; + + } else if (isELFDataSym(GV)) { + ELFSection &ES = + getSection(S->getName(), ELFSection::SHT_PROGBITS, SectionFlags); + GblSym->SectionIdx = ES.SectionIdx; + + // GblSym->Value should contain the symbol offset inside the section, + // and all symbols should start on their required alignment boundary + ES.Align = std::max(ES.Align, Align); + GblSym->Value = (ES.size() + (Align-1)) & (-Align); + ES.emitAlignment(ES.Align); + + // Emit the global to the data section 'ES' + EmitGlobalConstant(GVar->getInitializer(), ES); + } } + + if (!GV->hasPrivateLinkage()) + SymbolList.push_back(GblSym); } void ELFWriter::EmitGlobalConstantStruct(const ConstantStruct *CVS, @@ -339,9 +354,9 @@ void ELFWriter::EmitGlobalConstant(const Constant *CV, ELFSection &GblS) { else if (CFP->getType() == Type::FloatTy) GblS.emitWord32(Val); else if (CFP->getType() == Type::X86_FP80Ty) { - assert(0 && "X86_FP80Ty global emission not implemented"); + llvm_unreachable("X86_FP80Ty global emission not implemented"); } else if (CFP->getType() == Type::PPC_FP128Ty) - assert(0 && "PPC_FP128Ty global emission not implemented"); + llvm_unreachable("PPC_FP128Ty global emission not implemented"); return; } else if (const ConstantInt *CI = dyn_cast(CV)) { if (Size == 4) @@ -349,7 +364,7 @@ void ELFWriter::EmitGlobalConstant(const Constant *CV, ELFSection &GblS) { else if (Size == 8) GblS.emitWord64(CI->getZExtValue()); else - assert(0 && "LargeInt global emission not implemented"); + llvm_unreachable("LargeInt global emission not implemented"); return; } else if (const ConstantVector *CP = dyn_cast(CV)) { const VectorType *PTy = CP->getType(); @@ -357,7 +372,7 @@ void ELFWriter::EmitGlobalConstant(const Constant *CV, ELFSection &GblS) { EmitGlobalConstant(CP->getOperand(I), GblS); return; } - assert(0 && "unknown global constant"); + llvm_unreachable("unknown global constant"); } @@ -378,7 +393,7 @@ bool ELFWriter::doFinalization(Module &M) { // Build and emit data, bss and "common" sections. for (Module::global_iterator I = M.global_begin(), E = M.global_end(); I != E; ++I) { - EmitGlobalVar(I); + EmitGlobal(I); GblSymLookup[I] = 0; } @@ -391,15 +406,7 @@ bool ELFWriter::doFinalization(Module &M) { if (GblSymLookup.find(*I) != GblSymLookup.end()) continue; - if (GlobalVariable *GV = dyn_cast(*I)) { - EmitGlobalVar(GV); - } else if (Function *F = dyn_cast(*I)) { - // If function is not in GblSymLookup, it doesn't have a body, - // so emit the symbol as a function declaration (no section associated) - EmitFunctionDeclaration(F); - } else { - assert("unknown howto handle pending global"); - } + EmitGlobal(*I); GblSymLookup[*I] = 0; } @@ -407,23 +414,17 @@ bool ELFWriter::doFinalization(Module &M) { if (TAI->getNonexecutableStackDirective()) getNonExecStackSection(); - // Emit a symbol for each section created until now - for (std::map::iterator I = SectionLookup.begin(), - E = SectionLookup.end(); I != E; ++I) { - ELFSection *ES = I->second; - - // Skip null section - if (ES->SectionIdx == 0) continue; - - ELFSym SectionSym(0); - SectionSym.SectionIdx = ES->SectionIdx; - SectionSym.Size = 0; - SectionSym.setBind(ELFSym::STB_LOCAL); - SectionSym.setType(ELFSym::STT_SECTION); - SectionSym.setVisibility(ELFSym::STV_DEFAULT); - - // Local symbols go in the list front - SymbolList.push_front(SectionSym); + // Emit a symbol for each section created until now, skip null section + for (unsigned i = 1, e = SectionList.size(); i < e; ++i) { + ELFSection &ES = *SectionList[i]; + ELFSym *SectionSym = new ELFSym(0); + SectionSym->SectionIdx = ES.SectionIdx; + SectionSym->Size = 0; + SectionSym->setBind(ELFSym::STB_LOCAL); + SectionSym->setType(ELFSym::STT_SECTION); + SectionSym->setVisibility(ELFSym::STV_DEFAULT); + SymbolList.push_back(SectionSym); + ES.Sym = SymbolList.back(); } // Emit string table @@ -442,6 +443,7 @@ bool ELFWriter::doFinalization(Module &M) { OutputSectionsAndSectionTable(); // We are done with the abstract symbols. + SymbolList.clear(); SectionList.clear(); NumSections = 0; @@ -454,26 +456,26 @@ bool ELFWriter::doFinalization(Module &M) { void ELFWriter::EmitRelocations() { // Create Relocation sections for each section which needs it. - for (std::list::iterator I = SectionList.begin(), - E = SectionList.end(); I != E; ++I) { + for (unsigned i=0, e=SectionList.size(); i != e; ++i) { + ELFSection &S = *SectionList[i]; // This section does not have relocations - if (!I->hasRelocations()) continue; + if (!S.hasRelocations()) continue; - // Get the relocation section for section 'I' + // Get the relocation section for section 'S' bool HasRelA = TEW->hasRelocationAddend(); - ELFSection &RelSec = getRelocSection(I->getName(), HasRelA, + ELFSection &RelSec = getRelocSection(S.getName(), HasRelA, TEW->getPrefELFAlignment()); // 'Link' - Section hdr idx of the associated symbol table // 'Info' - Section hdr idx of the section to which the relocation applies ELFSection &SymTab = getSymbolTableSection(); RelSec.Link = SymTab.SectionIdx; - RelSec.Info = I->SectionIdx; + RelSec.Info = S.SectionIdx; RelSec.EntSize = TEW->getRelocationEntrySize(); // Get the relocations from Section - std::vector Relos = I->getRelocations(); + std::vector Relos = S.getRelocations(); for (std::vector::iterator MRI = Relos.begin(), MRE = Relos.end(); MRI != MRE; ++MRI) { MachineRelocation &MR = *MRI; @@ -487,7 +489,7 @@ void ELFWriter::EmitRelocations() { // Target specific ELF relocation type unsigned RelType = TEW->getRelocationType(MR.getRelocationType()); - // Constant addend used to compute the value to be stored + // Constant addend used to compute the value to be stored // into the relocatable field int64_t Addend = 0; @@ -498,15 +500,10 @@ void ELFWriter::EmitRelocations() { SymIdx = GblSymLookup[G]; Addend = TEW->getAddendForRelTy(RelType); } else { + // Get the symbol index for the section symbol referenced + // by the relocation unsigned SectionIdx = MR.getConstantVal(); - // TODO: use a map for this. - for (std::list::iterator I = SymbolList.begin(), - E = SymbolList.end(); I != E; ++I) - if ((SectionIdx == I->SectionIdx) && - (I->getType() == ELFSym::STT_SECTION)) { - SymIdx = I->SymTabIdx; - break; - } + SymIdx = SectionList[SectionIdx]->Sym->SymTabIdx; Addend = (uint64_t)MR.getResultPointer(); } @@ -547,7 +544,7 @@ void ELFWriter::EmitSymbol(BinaryObject &SymbolTable, ELFSym &Sym) { /// EmitSectionHeader - Write section 'Section' header in 'SHdrTab' /// Section Header Table -void ELFWriter::EmitSectionHeader(BinaryObject &SHdrTab, +void ELFWriter::EmitSectionHeader(BinaryObject &SHdrTab, const ELFSection &SHdr) { SHdrTab.emitWord32(SHdr.NameIdx); SHdrTab.emitWord32(SHdr.Type); @@ -581,20 +578,19 @@ void ELFWriter::EmitStringTable() { // Set the zero'th symbol to a null byte, as required. StrTab.emitByte(0); - // Walk on the symbol list and write symbol names into the - // string table. + // Walk on the symbol list and write symbol names into the string table. unsigned Index = 1; - for (std::list::iterator I = SymbolList.begin(), - E = SymbolList.end(); I != E; ++I) { + for (ELFSymIter I=SymbolList.begin(), E=SymbolList.end(); I != E; ++I) { + ELFSym &Sym = *(*I); // Use the name mangler to uniquify the LLVM symbol. std::string Name; - if (I->GV) Name.append(Mang->getValueName(I->GV)); + if (Sym.GV) Name.append(Mang->getMangledName(Sym.GV)); if (Name.empty()) { - I->NameIdx = 0; + Sym.NameIdx = 0; } else { - I->NameIdx = Index; + Sym.NameIdx = Index; StrTab.emitString(Name); // Keep track of the number of bytes emitted to this section. @@ -605,11 +601,38 @@ void ELFWriter::EmitStringTable() { StrTab.Size = Index; } +// SortSymbols - On the symbol table local symbols must come before +// all other symbols with non-local bindings. The return value is +// the position of the first non local symbol. +unsigned ELFWriter::SortSymbols() { + unsigned FirstNonLocalSymbol; + std::vector LocalSyms, OtherSyms; + + for (ELFSymIter I=SymbolList.begin(), E=SymbolList.end(); I != E; ++I) { + if ((*I)->isLocalBind()) + LocalSyms.push_back(*I); + else + OtherSyms.push_back(*I); + } + SymbolList.clear(); + FirstNonLocalSymbol = LocalSyms.size(); + + for (unsigned i = 0; i < FirstNonLocalSymbol; ++i) + SymbolList.push_back(LocalSyms[i]); + + for (ELFSymIter I=OtherSyms.begin(), E=OtherSyms.end(); I != E; ++I) + SymbolList.push_back(*I); + + LocalSyms.clear(); + OtherSyms.clear(); + + return FirstNonLocalSymbol; +} + /// EmitSymbolTable - Emit the symbol table itself. void ELFWriter::EmitSymbolTable() { if (!SymbolList.size()) return; // Empty symbol table. - unsigned FirstNonLocalSymbol = 1; // Now that we have emitted the string table and know the offset into the // string table of each symbol, emit the symbol table itself. ELFSection &SymTab = getSymbolTableSection(); @@ -622,29 +645,26 @@ void ELFWriter::EmitSymbolTable() { SymTab.EntSize = TEW->getSymTabEntrySize(); // The first entry in the symtab is the null symbol - ELFSym NullSym = ELFSym(0); - EmitSymbol(SymTab, NullSym); + SymbolList.insert(SymbolList.begin(), new ELFSym(0)); - // Emit all the symbols to the symbol table. Skip the null - // symbol, cause it's emitted already - unsigned Index = 1; - for (std::list::iterator I = SymbolList.begin(), - E = SymbolList.end(); I != E; ++I, ++Index) { - // Keep track of the first non-local symbol - if (I->getBind() == ELFSym::STB_LOCAL) - FirstNonLocalSymbol++; + // Reorder the symbol table with local symbols first! + unsigned FirstNonLocalSymbol = SortSymbols(); + + // Emit all the symbols to the symbol table. + for (unsigned i = 0, e = SymbolList.size(); i < e; ++i) { + ELFSym &Sym = *SymbolList[i]; // Emit symbol to the symbol table - EmitSymbol(SymTab, *I); + EmitSymbol(SymTab, Sym); // Record the symbol table index for each global value - if (I->GV) - GblSymLookup[I->GV] = Index; + if (Sym.GV) GblSymLookup[Sym.GV] = i; // Keep track on the symbol index into the symbol table - I->SymTabIdx = Index; + Sym.SymTabIdx = i; } + // One greater than the symbol table index of the last local symbol SymTab.Info = FirstNonLocalSymbol; SymTab.Size = SymTab.size(); } @@ -664,15 +684,15 @@ void ELFWriter::EmitSectionTableStringTable() { // the string table. unsigned Index = 0; - for (std::list::iterator I = SectionList.begin(), - E = SectionList.end(); I != E; ++I) { + for (ELFSectionIter I=SectionList.begin(), E=SectionList.end(); I != E; ++I) { + ELFSection &S = *(*I); // Set the index into the table. Note if we have lots of entries with // common suffixes, we could memoize them here if we cared. - I->NameIdx = Index; - SHStrTab.emitString(I->getName()); + S.NameIdx = Index; + SHStrTab.emitString(S.getName()); // Keep track of the number of bytes emitted to this section. - Index += I->getName().size()+1; + Index += S.getName().size()+1; } // Set the size of .shstrtab now that we know what it is. @@ -687,29 +707,24 @@ void ELFWriter::OutputSectionsAndSectionTable() { // Pass #1: Compute the file offset for each section. size_t FileOff = ElfHdr.size(); // File header first. - // Adjust alignment of all section if needed. - for (std::list::iterator I = SectionList.begin(), - E = SectionList.end(); I != E; ++I) { - - // Section idx 0 has 0 offset - if (!I->SectionIdx) - continue; - - if (!I->size()) { - I->Offset = FileOff; + // Adjust alignment of all section if needed, skip the null section. + for (unsigned i=1, e=SectionList.size(); i < e; ++i) { + ELFSection &ES = *SectionList[i]; + if (!ES.size()) { + ES.Offset = FileOff; continue; } // Update Section size - if (!I->Size) - I->Size = I->size(); + if (!ES.Size) + ES.Size = ES.size(); // Align FileOff to whatever the alignment restrictions of the section are. - if (I->Align) - FileOff = (FileOff+I->Align-1) & ~(I->Align-1); + if (ES.Align) + FileOff = (FileOff+ES.Align-1) & ~(ES.Align-1); - I->Offset = FileOff; - FileOff += I->Size; + ES.Offset = FileOff; + FileOff += ES.Size; } // Align Section Header. @@ -733,8 +748,8 @@ void ELFWriter::OutputSectionsAndSectionTable() { BinaryObject SHdrTable(isLittleEndian, is64Bit); // Emit all of sections to the file and build the section header table. - while (!SectionList.empty()) { - ELFSection &S = *SectionList.begin(); + for (ELFSectionIter I=SectionList.begin(), E=SectionList.end(); I != E; ++I) { + ELFSection &S = *(*I); DOUT << "SectionIdx: " << S.SectionIdx << ", Name: " << S.getName() << ", Size: " << S.Size << ", Offset: " << S.Offset << ", SectionData Size: " << S.size() << "\n"; @@ -751,7 +766,6 @@ void ELFWriter::OutputSectionsAndSectionTable() { } EmitSectionHeader(SHdrTable, S); - SectionList.pop_front(); } // Align output for the section table.