From 746e3bb3547d848af86c4d677dfdc2c4481c7518 Mon Sep 17 00:00:00 2001 From: Bruno Cardoso Lopes Date: Mon, 27 Jul 2009 18:54:47 +0000 Subject: [PATCH] Handle external symbols for ELF and add some static methods to ELFSym git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@77232 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/ELF.h | 77 +++++++++++++++++++++++++++++++--- lib/CodeGen/ELFCodeEmitter.cpp | 15 +++---- lib/CodeGen/ELFWriter.cpp | 76 +++++++++++++++++++++++---------- lib/CodeGen/ELFWriter.h | 33 ++++++++++----- 4 files changed, 155 insertions(+), 46 deletions(-) diff --git a/lib/CodeGen/ELF.h b/lib/CodeGen/ELF.h index d4dc151494c..cd0c68a7a2e 100644 --- a/lib/CodeGen/ELF.h +++ b/lib/CodeGen/ELF.h @@ -56,9 +56,74 @@ namespace llvm { /// 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 symbols are related to llvm ones by being one of the two llvm + // types, for the other ones (section, file, func) a null pointer is + // assumed. + union { + const GlobalValue *GV; // If this is a pointer to a GV + const char *Ext; // If this is a pointer to a named symbol + } Source; + + // Describes from which source type this ELF symbol comes from, + // they can be GlobalValue, ExternalSymbol or neither. + enum { + isGV, // The Source.GV field is valid. + isExtSym, // The Source.ExtSym field is valid. + isOther // Not a GlobalValue or External Symbol + }; + unsigned SourceType; + + bool isGlobalValue() { return SourceType == isGV; } + bool isExternalSym() { return SourceType == isExtSym; } + + // getGlobalValue - If this is a global value which originated the + // elf symbol, return a reference to it. + const GlobalValue *getGlobalValue() { + assert(SourceType == isGV && "This is not a global value"); + return Source.GV; + }; + + // getExternalSym - If this is an external symbol which originated the + // elf symbol, return a reference to it. + const char *getExternalSymbol() { + assert(SourceType == isExtSym && "This is not an external symbol"); + return Source.Ext; + }; + + // getGV - From a global value return a elf symbol to represent it + static ELFSym *getGV(const GlobalValue *GV, unsigned Bind, + unsigned Type, unsigned Visibility) { + ELFSym *Sym = new ELFSym(); + Sym->Source.GV = GV; + Sym->setBind(Bind); + Sym->setType(Type); + Sym->setVisibility(Visibility); + Sym->SourceType = isGV; + return Sym; + } + + // getExtSym - Create and return an elf symbol to represent an + // external symbol + static ELFSym *getExtSym(const char *Ext) { + ELFSym *Sym = new ELFSym(); + Sym->Source.Ext = Ext; + Sym->setBind(STB_GLOBAL); + Sym->setType(STT_NOTYPE); + Sym->setVisibility(STV_DEFAULT); + Sym->SourceType = isExtSym; + return Sym; + } + + // getSectionSym - Returns a elf symbol to represent an elf section + static ELFSym *getSectionSym() { + ELFSym *Sym = new ELFSym(); + Sym->setBind(ELFSym::STB_LOCAL); + Sym->setType(ELFSym::STT_SECTION); + Sym->setVisibility(ELFSym::STV_DEFAULT); + Sym->SourceType = isOther; + return Sym; + } // ELF specific fields unsigned NameIdx; // Index in .strtab of name, once emitted. @@ -92,9 +157,9 @@ namespace llvm { 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) {} + ELFSym() : SourceType(isOther), 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; } diff --git a/lib/CodeGen/ELFCodeEmitter.cpp b/lib/CodeGen/ELFCodeEmitter.cpp index 1c27428cc33..a62a884e04b 100644 --- a/lib/CodeGen/ELFCodeEmitter.cpp +++ b/lib/CodeGen/ELFCodeEmitter.cpp @@ -69,16 +69,11 @@ void ELFCodeEmitter::startFunction(MachineFunction &MF) { bool ELFCodeEmitter::finishFunction(MachineFunction &MF) { // Add a symbol to represent the function. const Function *F = MF.getFunction(); - ELFSym *FnSym = new ELFSym(F); - FnSym->setType(ELFSym::STT_FUNC); - FnSym->setBind(EW.getGlobalELFBinding(F)); - FnSym->setVisibility(EW.getGlobalELFVisibility(F)); + ELFSym *FnSym = ELFSym::getGV(F, EW.getGlobalELFBinding(F), ELFSym::STT_FUNC, + EW.getGlobalELFVisibility(F)); FnSym->SectionIdx = ES->SectionIdx; FnSym->Size = ES->getCurrentPCOffset()-FnStartOff; - - // keep track of the emitted function leaving its symbol index as zero - // to be patched up later when emitting the symbol table - EW.setGlobalSymLookup(F, 0); + EW.addGlobalSymbol(F); // Offset from start of Section FnSym->Value = FnStartOff; @@ -108,7 +103,9 @@ bool ELFCodeEmitter::finishFunction(MachineFunction &MF) { MachineRelocation &MR = Relocations[i]; intptr_t Addr; if (MR.isGlobalValue()) { - EW.PendingGlobals.insert(MR.getGlobalValue()); + EW.addGlobalSymbol(MR.getGlobalValue()); + } else if (MR.isExternalSymbol()) { + EW.addExternalSymbol(MR.getExternalSymbol()); } else if (MR.isBasicBlock()) { Addr = getMachineBasicBlockAddress(MR.getBasicBlock()); MR.setConstantVal(ES->SectionIdx); diff --git a/lib/CodeGen/ELFWriter.cpp b/lib/CodeGen/ELFWriter.cpp index c61d4210cb3..f2a9bf34e58 100644 --- a/lib/CodeGen/ELFWriter.cpp +++ b/lib/CodeGen/ELFWriter.cpp @@ -144,6 +144,21 @@ bool ELFWriter::doInitialization(Module &M) { return false; } +// addGlobalSymbol - Add a global to be processed and to the +// global symbol lookup, use a zero index for non private symbols +// because the table index will be determined later. +void ELFWriter::addGlobalSymbol(const GlobalValue *GV) { + PendingGlobals.insert(GV); +} + +// addExternalSymbol - Add the external to be processed and to the +// external symbol lookup, use a zero index because the symbol +// table index will be determined later +void ELFWriter::addExternalSymbol(const char *External) { + PendingExternals.insert(External); + ExtSymLookup[External] = 0; +} + // Get jump table section on the section name returned by TAI ELFSection &ELFWriter::getJumpTableSection() { unsigned Align = TM.getTargetData()->getPointerABIAlignment(); @@ -169,7 +184,7 @@ ELFSection &ELFWriter::getConstantPoolSection(MachineConstantPoolEntry &CPE) { default: Kind = SectionKind::get(SectionKind::MergeableConst,false); break; } } - + return getSection(TAI->getSectionForMergeableConstant(Kind)->getName(), ELFSection::SHT_PROGBITS, ELFSection::SHF_MERGE | ELFSection::SHF_ALLOC, @@ -278,12 +293,18 @@ void ELFWriter::EmitGlobal(const GlobalValue *GV) { if (GblSymLookup.find(GV) != GblSymLookup.end()) return; + // If the global is a function already emited in the text section + // just add it to the global symbol lookup with a zero index to be + // patched up later. + if (isa(GV) && !GV->isDeclaration()) { + GblSymLookup[GV] = 0; + return; + } + // 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)); + ELFSym *GblSym = ELFSym::getGV(GV, SymBind, getGlobalELFType(GV), + getGlobalELFVisibility(GV)); if (isELFUndefSym(GV)) { GblSym->SectionIdx = ELFSection::SHN_UNDEF; @@ -341,16 +362,18 @@ void ELFWriter::EmitGlobal(const GlobalValue *GV) { } } - // Private symbols must never go to the symbol table. - unsigned SymIdx = 0; if (GV->hasPrivateLinkage()) { + // For a private symbols, keep track of the index inside the + // private list since it will never go to the symbol table and + // won't be patched up later. PrivateSyms.push_back(GblSym); - SymIdx = PrivateSyms.size()-1; + GblSymLookup[GV] = PrivateSyms.size()-1; } else { + // Non private symbol are left with zero indices until they are patched + // up during the symbol table emition (where the indicies are created). SymbolList.push_back(GblSym); + GblSymLookup[GV] = 0; } - - setGlobalSymLookup(GV, SymIdx); } void ELFWriter::EmitGlobalConstantStruct(const ConstantStruct *CVS, @@ -478,10 +501,15 @@ bool ELFWriter::doFinalization(Module &M) { EmitGlobal(I); // Emit all pending globals - for (SetVector::const_iterator I = PendingGlobals.begin(), - E = PendingGlobals.end(); I != E; ++I) + for (PendingGblsIter I = PendingGlobals.begin(), E = PendingGlobals.end(); + I != E; ++I) EmitGlobal(*I); + // Emit all pending externals + for (PendingExtsIter I = PendingExternals.begin(), E = PendingExternals.end(); + I != E; ++I) + SymbolList.push_back(ELFSym::getExtSym(*I)); + // Emit non-executable stack note if (TAI->getNonexecutableStackDirective()) getNonExecStackSection(); @@ -489,12 +517,8 @@ bool ELFWriter::doFinalization(Module &M) { // 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); + ELFSym *SectionSym = ELFSym::getSectionSym(); 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(); } @@ -589,6 +613,10 @@ void ELFWriter::EmitRelocations() { } else { Addend = TEW->getDefaultAddendForRelTy(RelType); } + } else if (MR.isExternalSymbol()) { + const char *ExtSym = MR.getExternalSymbol(); + SymIdx = ExtSymLookup[ExtSym]; + Addend = TEW->getDefaultAddendForRelTy(RelType); } else { // Get the symbol index for the section symbol unsigned SectionIdx = MR.getConstantVal(); @@ -695,7 +723,10 @@ void ELFWriter::EmitStringTable() { // Use the name mangler to uniquify the LLVM symbol. std::string Name; - if (Sym.GV) Name.append(Mang->getMangledName(Sym.GV)); + if (Sym.isGlobalValue()) + Name.append(Mang->getMangledName(Sym.getGlobalValue())); + else if (Sym.isExternalSym()) + Name.append(Sym.getExternalSymbol()); if (Name.empty()) { Sym.NameIdx = 0; @@ -755,7 +786,7 @@ void ELFWriter::EmitSymbolTable() { SymTab.EntSize = TEW->getSymTabEntrySize(); // The first entry in the symtab is the null symbol - SymbolList.insert(SymbolList.begin(), new ELFSym(0)); + SymbolList.insert(SymbolList.begin(), new ELFSym()); // Reorder the symbol table with local symbols first! unsigned FirstNonLocalSymbol = SortSymbols(); @@ -767,8 +798,11 @@ void ELFWriter::EmitSymbolTable() { // Emit symbol to the symbol table EmitSymbol(SymTab, Sym); - // Record the symbol table index for each global value - if (Sym.GV) setGlobalSymLookup(Sym.GV, i); + // Record the symbol table index for each symbol + if (Sym.isGlobalValue()) + GblSymLookup[Sym.getGlobalValue()] = i; + else if (Sym.isExternalSym()) + ExtSymLookup[Sym.getExternalSymbol()] = i; // Keep track on the symbol index into the symbol table Sym.SymTabIdx = i; diff --git a/lib/CodeGen/ELFWriter.h b/lib/CodeGen/ELFWriter.h index 8dcd970cfc6..021fbeb5d59 100644 --- a/lib/CodeGen/ELFWriter.h +++ b/lib/CodeGen/ELFWriter.h @@ -38,6 +38,8 @@ namespace llvm { typedef std::vector::iterator ELFSymIter; typedef std::vector::iterator ELFSectionIter; + typedef SetVector::const_iterator PendingGblsIter; + typedef SetVector::const_iterator PendingExtsIter; /// ELFWriter - This class implements the common target-independent code for /// writing ELF files. Targets should derive a class from this to @@ -108,11 +110,22 @@ namespace llvm { /// the SectionList. Used to quickly gather the Section Index from TAI names std::map SectionLookup; + /// PendingGlobals - Globals not processed as symbols yet. + SetVector PendingGlobals; + /// GblSymLookup - This is a mapping from global value to a symbol index /// in the symbol table or private symbols list. This is useful since reloc - /// symbol references must be quickly mapped to their indices on the lists + /// symbol references must be quickly mapped to their indices on the lists. std::map GblSymLookup; + /// PendingExternals - Externals not processed as symbols yet. + SetVector PendingExternals; + + /// ExtSymLookup - This is a mapping from externals to a symbol index + /// in the symbol table list. This is useful since reloc symbol references + /// must be quickly mapped to their symbol table indices. + std::map ExtSymLookup; + /// 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. @@ -122,11 +135,6 @@ namespace llvm { /// present in the SymbolList. std::vector PrivateSyms; - /// 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 PendingGlobals; - // 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 @@ -212,10 +220,15 @@ namespace llvm { unsigned getGlobalELFVisibility(const GlobalValue *GV); unsigned getElfSectionFlags(SectionKind Kind); - // setGlobalSymLookup - Set global value 'GV' with 'Index' in the lookup map - void setGlobalSymLookup(const GlobalValue *GV, unsigned Index) { - GblSymLookup[GV] = Index; - } + // addGlobalSymbol - Add a global to be processed and to the + // global symbol lookup, use a zero index for non private symbols + // because the table index will be determined later. + void addGlobalSymbol(const GlobalValue *GV); + + // addExternalSymbol - Add the external to be processed and to the + // external symbol lookup, use a zero index because the symbol + // table index will be determined later + void addExternalSymbol(const char *External); // As we complete the ELF file, we need to update fields in the ELF header // (e.g. the location of the section table). These members keep track of -- 2.34.1