diff options
Diffstat (limited to 'lib/CodeGen')
-rw-r--r-- | lib/CodeGen/ELF.h | 133 | ||||
-rw-r--r-- | lib/CodeGen/ELFCodeEmitter.cpp | 25 | ||||
-rw-r--r-- | lib/CodeGen/ELFWriter.cpp | 196 | ||||
-rw-r--r-- | lib/CodeGen/ELFWriter.h | 29 |
4 files changed, 192 insertions, 191 deletions
diff --git a/lib/CodeGen/ELF.h b/lib/CodeGen/ELF.h index 2c37c57579..730ba479ac 100644 --- a/lib/CodeGen/ELF.h +++ b/lib/CodeGen/ELF.h @@ -52,6 +52,70 @@ namespace llvm { EV_CURRENT = 1 }; + /// ELFSym - This struct contains information about each symbol that is + /// added to logical symbol table for the module. This is eventually + /// turned into a real symbol table in the file. + struct ELFSym { + // The global value this symbol matches. This should be null if the symbol + // is not a global value. + const GlobalValue *GV; + + // ELF specific fields + unsigned NameIdx; // Index in .strtab of name, once emitted. + uint64_t Value; + unsigned Size; + uint8_t Info; + uint8_t Other; + unsigned short SectionIdx; + + // Symbol index into the Symbol table + unsigned SymTabIdx; + + enum { + STB_LOCAL = 0, + STB_GLOBAL = 1, + STB_WEAK = 2 + }; + + enum { + STT_NOTYPE = 0, + STT_OBJECT = 1, + STT_FUNC = 2, + STT_SECTION = 3, + STT_FILE = 4 + }; + + enum { + STV_DEFAULT = 0, // Visibility is specified by binding type + STV_INTERNAL = 1, // Defined by processor supplements + STV_HIDDEN = 2, // Not visible to other components + STV_PROTECTED = 3 // Visible in other components but not preemptable + }; + + ELFSym(const GlobalValue *gv) : GV(gv), NameIdx(0), Value(0), + Size(0), Info(0), Other(STV_DEFAULT), + SectionIdx(0), SymTabIdx(0) {} + + unsigned getBind() const { return (Info >> 4) & 0xf; } + unsigned getType() const { return Info & 0xf; } + bool isLocalBind() const { return getBind() == STB_LOCAL; } + + void setBind(unsigned X) { + assert(X == (X & 0xF) && "Bind value out of range!"); + Info = (Info & 0x0F) | (X << 4); + } + + void setType(unsigned X) { + assert(X == (X & 0xF) && "Type value out of range!"); + Info = (Info & 0xF0) | X; + } + + void setVisibility(unsigned V) { + assert(V == (V & 0x3) && "Visibility value out of range!"); + Other = V; + } + }; + /// ELFSection - This struct contains information about each section that is /// emitted to the file. This is eventually turned into the section header /// table at the end of the file. @@ -117,73 +181,12 @@ namespace llvm { /// SectionIdx - The number of the section in the Section Table. unsigned short SectionIdx; + /// Sym - The symbol to represent this section if it has one. + ELFSym *Sym; + ELFSection(const std::string &name, bool isLittleEndian, bool is64Bit) : BinaryObject(name, isLittleEndian, is64Bit), Type(0), Flags(0), Addr(0), - Offset(0), Size(0), Link(0), Info(0), Align(0), EntSize(0) {} - }; - - /// ELFSym - This struct contains information about each symbol that is - /// added to logical symbol table for the module. This is eventually - /// turned into a real symbol table in the file. - struct ELFSym { - // The global value this symbol matches. This should be null if the symbol - // is not a global value. - const GlobalValue *GV; - - // ELF specific fields - unsigned NameIdx; // Index in .strtab of name, once emitted. - uint64_t Value; - unsigned Size; - uint8_t Info; - uint8_t Other; - unsigned short SectionIdx; - - // Symbol index into the Symbol table - unsigned SymTabIdx; - - enum { - STB_LOCAL = 0, - STB_GLOBAL = 1, - STB_WEAK = 2 - }; - - enum { - STT_NOTYPE = 0, - STT_OBJECT = 1, - STT_FUNC = 2, - STT_SECTION = 3, - STT_FILE = 4 - }; - - enum { - STV_DEFAULT = 0, // Visibility is specified by binding type - STV_INTERNAL = 1, // Defined by processor supplements - STV_HIDDEN = 2, // Not visible to other components - STV_PROTECTED = 3 // Visible in other components but not preemptable - }; - - ELFSym(const GlobalValue *gv) : GV(gv), NameIdx(0), Value(0), - Size(0), Info(0), Other(STV_DEFAULT), - SectionIdx(ELFSection::SHN_UNDEF), - SymTabIdx(0) {} - - unsigned getBind() { return (Info >> 4) & 0xf; } - unsigned getType() { return Info & 0xf; } - - void setBind(unsigned X) { - assert(X == (X & 0xF) && "Bind value out of range!"); - Info = (Info & 0x0F) | (X << 4); - } - - void setType(unsigned X) { - assert(X == (X & 0xF) && "Type value out of range!"); - Info = (Info & 0xF0) | X; - } - - void setVisibility(unsigned V) { - assert(V == (V & 0x3) && "Type value out of range!"); - Other = V; - } + Offset(0), Size(0), Link(0), Info(0), Align(0), EntSize(0), Sym(0) {} }; /// ELFRelocation - This class contains all the information necessary to diff --git a/lib/CodeGen/ELFCodeEmitter.cpp b/lib/CodeGen/ELFCodeEmitter.cpp index 5133e74298..1d150032c3 100644 --- a/lib/CodeGen/ELFCodeEmitter.cpp +++ b/lib/CodeGen/ELFCodeEmitter.cpp @@ -60,23 +60,18 @@ void ELFCodeEmitter::startFunction(MachineFunction &MF) { bool ELFCodeEmitter::finishFunction(MachineFunction &MF) { // Add a symbol to represent the function. const Function *F = MF.getFunction(); - ELFSym FnSym(F); - FnSym.setType(ELFSym::STT_FUNC); - FnSym.setBind(EW.getGlobalELFBinding(F)); - FnSym.setVisibility(EW.getGlobalELFVisibility(F)); - FnSym.SectionIdx = ES->SectionIdx; - FnSym.Size = ES->getCurrentPCOffset()-FnStartOff; + ELFSym *FnSym = new ELFSym(F); + FnSym->setType(ELFSym::STT_FUNC); + FnSym->setBind(EW.getGlobalELFBinding(F)); + FnSym->setVisibility(EW.getGlobalELFVisibility(F)); + FnSym->SectionIdx = ES->SectionIdx; + FnSym->Size = ES->getCurrentPCOffset()-FnStartOff; // Offset from start of Section - FnSym.Value = FnStartOff; - - // Locals should go on the symbol list front - if (!F->hasPrivateLinkage()) { - if (FnSym.getBind() == ELFSym::STB_LOCAL) - EW.SymbolList.push_front(FnSym); - else - EW.SymbolList.push_back(FnSym); - } + FnSym->Value = FnStartOff; + + if (!F->hasPrivateLinkage()) + EW.SymbolList.push_back(FnSym); // Emit constant pool to appropriate section(s) emitConstantPool(MF.getConstantPool()); diff --git a/lib/CodeGen/ELFWriter.cpp b/lib/CodeGen/ELFWriter.cpp index 05b736147c..a89dae4637 100644 --- a/lib/CodeGen/ELFWriter.cpp +++ b/lib/CodeGen/ELFWriter.cpp @@ -235,13 +235,13 @@ void ELFWriter::EmitGlobal(const GlobalValue *GV) { // Handle ELF Bind, Visibility and Type for the current symbol unsigned SymBind = getGlobalELFBinding(GV); - ELFSym GblSym(GV); - GblSym.setBind(SymBind); - GblSym.setVisibility(getGlobalELFVisibility(GV)); - GblSym.setType(getGlobalELFType(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; + GblSym->SectionIdx = ELFSection::SHN_UNDEF; } else { assert(isa<GlobalVariable>(GV) && "GV not a global variable!"); const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV); @@ -254,41 +254,41 @@ void ELFWriter::EmitGlobal(const GlobalValue *GV) { const TargetData *TD = TM.getTargetData(); unsigned Align = TD->getPreferredAlignment(GVar); unsigned Size = TD->getTypeAllocSize(GVar->getInitializer()->getType()); - GblSym.Size = Size; + GblSym->Size = Size; if (isELFCommonSym(GV)) { - GblSym.SectionIdx = ELFSection::SHN_COMMON; + 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; + GblSym->Value = Align; } else if (isELFBssSym(GV)) { ELFSection &ES = getSection(S->getName(), ELFSection::SHT_NOBITS, SectionFlags); - GblSym.SectionIdx = ES.SectionIdx; + 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. + // 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; + 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->SectionIdx = ES.SectionIdx; - // GblSym.Value should contain the symbol offset inside the section, + // 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); + GblSym->Value = (ES.size() + (Align-1)) & (-Align); ES.emitAlignment(ES.Align); // Emit the global to the data section 'ES' @@ -296,13 +296,8 @@ void ELFWriter::EmitGlobal(const GlobalValue *GV) { } } - // 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); - } + if (!GV->hasPrivateLinkage()) + SymbolList.push_back(GblSym); } void ELFWriter::EmitGlobalConstantStruct(const ConstantStruct *CVS, @@ -419,23 +414,17 @@ bool ELFWriter::doFinalization(Module &M) { if (TAI->getNonexecutableStackDirective()) getNonExecStackSection(); - // Emit a symbol for each section created until now - for (std::map<std::string, ELFSection*>::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 @@ -454,6 +443,7 @@ bool ELFWriter::doFinalization(Module &M) { OutputSectionsAndSectionTable(); // We are done with the abstract symbols. + SymbolList.clear(); SectionList.clear(); NumSections = 0; @@ -466,26 +456,26 @@ bool ELFWriter::doFinalization(Module &M) { void ELFWriter::EmitRelocations() { // Create Relocation sections for each section which needs it. - for (std::list<ELFSection>::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<MachineRelocation> Relos = I->getRelocations(); + std::vector<MachineRelocation> Relos = S.getRelocations(); for (std::vector<MachineRelocation>::iterator MRI = Relos.begin(), MRE = Relos.end(); MRI != MRE; ++MRI) { MachineRelocation &MR = *MRI; @@ -510,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<ELFSym>::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(); } @@ -596,17 +581,17 @@ void ELFWriter::EmitStringTable() { // Walk on the symbol list and write symbol names into the // string table. unsigned Index = 1; - for (std::list<ELFSym>::iterator I = SymbolList.begin(), - E = SymbolList.end(); I != E; ++I) { + for (unsigned i = 0, e = SymbolList.size(); i < e; ++i) { + ELFSym &Sym = *SymbolList[i]; // Use the name mangler to uniquify the LLVM symbol. std::string Name; - if (I->GV) Name.append(Mang->getMangledName(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. @@ -617,11 +602,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, i, e; + std::vector<ELFSym*> LocalSyms, OtherSyms; + + for (i = 0, e = SymbolList.size(); i < e; ++i) { + if (SymbolList[i]->isLocalBind()) + LocalSyms.push_back(SymbolList[i]); + else + OtherSyms.push_back(SymbolList[i]); + } + SymbolList.clear(); + FirstNonLocalSymbol = LocalSyms.size(); + + for (i = 0; i < FirstNonLocalSymbol; ++i) + SymbolList.push_back(LocalSyms[i]); + + for (i = 0, e = OtherSyms.size(); i < e; ++i) + SymbolList.push_back(OtherSyms[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(); @@ -634,29 +646,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<ELFSym>::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(); } @@ -676,15 +685,14 @@ void ELFWriter::EmitSectionTableStringTable() { // the string table. unsigned Index = 0; - for (std::list<ELFSection>::iterator I = SectionList.begin(), - E = SectionList.end(); I != E; ++I) { + for (unsigned i=0, e=SectionList.size(); i < e; ++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()); + SectionList[i]->NameIdx = Index; + SHStrTab.emitString(SectionList[i]->getName()); // Keep track of the number of bytes emitted to this section. - Index += I->getName().size()+1; + Index += SectionList[i]->getName().size()+1; } // Set the size of .shstrtab now that we know what it is. @@ -699,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<ELFSection>::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. @@ -745,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 (unsigned i=0, e=SectionList.size(); i < e; ++i) { + ELFSection &S = *SectionList[i]; DOUT << "SectionIdx: " << S.SectionIdx << ", Name: " << S.getName() << ", Size: " << S.Size << ", Offset: " << S.Offset << ", SectionData Size: " << S.size() << "\n"; @@ -763,7 +766,6 @@ void ELFWriter::OutputSectionsAndSectionTable() { } EmitSectionHeader(SHdrTable, S); - SectionList.pop_front(); } // Align output for the section table. diff --git a/lib/CodeGen/ELFWriter.h b/lib/CodeGen/ELFWriter.h index b0d7f3bc13..3cc50fe836 100644 --- a/lib/CodeGen/ELFWriter.h +++ b/lib/CodeGen/ELFWriter.h @@ -16,7 +16,6 @@ #include "llvm/ADT/SetVector.h" #include "llvm/CodeGen/MachineFunctionPass.h" -#include <list> #include <map> namespace llvm { @@ -95,13 +94,13 @@ namespace llvm { BinaryObject ElfHdr; /// SectionList - This is the list of sections that we have emitted to the - /// file. Once the file has been completely built, the section header table + /// file. Once the file has been completely built, the section header table /// is constructed from this info. - std::list<ELFSection> SectionList; + std::vector<ELFSection*> SectionList; unsigned NumSections; // Always = SectionList.size() /// SectionLookup - This is a mapping from section name to section number in - /// the SectionList. + /// the SectionList. Used to quickly gather the Section Index from TAI names std::map<std::string, ELFSection*> SectionLookup; /// GblSymLookup - This is a mapping from global value to a symbol index @@ -109,17 +108,18 @@ namespace llvm { /// must be quickly mapped to a symbol table index std::map<const GlobalValue*, uint32_t> GblSymLookup; - /// SymbolList - This is the list of symbols emitted to the symbol table - /// Local symbols go to the front and Globals to the back. - std::list<ELFSym> SymbolList; + /// SymbolList - This is the list of symbols emitted to the symbol table. + /// When the SymbolList is finally built, local symbols must be placed in + /// the beginning while non-locals at the end. + std::vector<ELFSym*> SymbolList; /// PendingGlobals - List of externally defined symbols that we have been /// asked to emit, but have not seen a reference to. When a reference /// is seen, the symbol will move from this list to the SymbolList. SetVector<GlobalValue*> PendingGlobals; - // Remove tab from section name prefix. This is necessary becase TAI - // sometimes return a section name prefixed with a "\t" char. This is + // Remove tab from section name prefix. This is necessary becase TAI + // sometimes return a section name prefixed with elf unused chars. This is // a little bit dirty. FIXME: find a better approach, maybe add more // methods to TAI to get the clean name? void fixNameForSection(std::string &Name) { @@ -140,14 +140,14 @@ namespace llvm { /// section if one does not already exist. ELFSection &getSection(const std::string &Name, unsigned Type, unsigned Flags = 0, unsigned Align = 0) { - std::string SectionName(Name); - fixNameForSection(SectionName); + std::string SName(Name); + fixNameForSection(SName); - ELFSection *&SN = SectionLookup[SectionName]; + ELFSection *&SN = SectionLookup[SName]; if (SN) return *SN; - SectionList.push_back(ELFSection(SectionName, isLittleEndian, is64Bit)); - SN = &SectionList.back(); + SectionList.push_back(new ELFSection(SName, isLittleEndian, is64Bit)); + SN = SectionList.back(); SN->SectionIdx = NumSections++; SN->Type = Type; SN->Flags = Flags; @@ -245,6 +245,7 @@ namespace llvm { void EmitSymbolTable(); void EmitStringTable(); void OutputSectionsAndSectionTable(); + unsigned SortSymbols(); }; } |