diff options
Diffstat (limited to 'llvm/lib/CodeGen')
| -rw-r--r-- | llvm/lib/CodeGen/ELF.h | 77 | ||||
| -rw-r--r-- | llvm/lib/CodeGen/ELFCodeEmitter.cpp | 15 | ||||
| -rw-r--r-- | llvm/lib/CodeGen/ELFWriter.cpp | 76 | ||||
| -rw-r--r-- | llvm/lib/CodeGen/ELFWriter.h | 33 | 
4 files changed, 155 insertions, 46 deletions
diff --git a/llvm/lib/CodeGen/ELF.h b/llvm/lib/CodeGen/ELF.h index d4dc151494c..cd0c68a7a2e 100644 --- a/llvm/lib/CodeGen/ELF.h +++ b/llvm/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/llvm/lib/CodeGen/ELFCodeEmitter.cpp b/llvm/lib/CodeGen/ELFCodeEmitter.cpp index 1c27428cc33..a62a884e04b 100644 --- a/llvm/lib/CodeGen/ELFCodeEmitter.cpp +++ b/llvm/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/llvm/lib/CodeGen/ELFWriter.cpp b/llvm/lib/CodeGen/ELFWriter.cpp index c61d4210cb3..f2a9bf34e58 100644 --- a/llvm/lib/CodeGen/ELFWriter.cpp +++ b/llvm/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<Function>(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<GlobalValue*>::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/llvm/lib/CodeGen/ELFWriter.h b/llvm/lib/CodeGen/ELFWriter.h index 8dcd970cfc6..021fbeb5d59 100644 --- a/llvm/lib/CodeGen/ELFWriter.h +++ b/llvm/lib/CodeGen/ELFWriter.h @@ -38,6 +38,8 @@ namespace llvm {    typedef std::vector<ELFSym*>::iterator ELFSymIter;    typedef std::vector<ELFSection*>::iterator ELFSectionIter; +  typedef SetVector<const GlobalValue*>::const_iterator PendingGblsIter; +  typedef SetVector<const char *>::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<std::string, ELFSection*> SectionLookup; +    /// PendingGlobals - Globals not processed as symbols yet. +    SetVector<const GlobalValue*> 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<const GlobalValue*, uint32_t> GblSymLookup; +    /// PendingExternals - Externals not processed as symbols yet. +    SetVector<const char *> 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<const char *, uint32_t> 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<ELFSym*> 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<GlobalValue*> 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  | 

