diff options
-rw-r--r-- | include/llvm/MC/MCAssembler.h | 32 | ||||
-rw-r--r-- | lib/MC/MCAssembler.cpp | 98 | ||||
-rw-r--r-- | lib/MC/MCMachOStreamer.cpp | 15 |
3 files changed, 128 insertions, 17 deletions
diff --git a/include/llvm/MC/MCAssembler.h b/include/llvm/MC/MCAssembler.h index aae5f08..b5ee501 100644 --- a/include/llvm/MC/MCAssembler.h +++ b/include/llvm/MC/MCAssembler.h @@ -16,6 +16,7 @@ #include "llvm/MC/MCValue.h" #include "llvm/Support/Casting.h" #include "llvm/Support/DataTypes.h" +#include <vector> // FIXME: Shouldn't be needed. namespace llvm { class raw_ostream; @@ -360,6 +361,12 @@ public: /// @} }; +// FIXME: This really doesn't belong here. See comments below. +struct IndirectSymbolData { + MCSymbol *Symbol; + MCSectionData *SectionData; +}; + class MCAssembler { public: typedef iplist<MCSectionData> SectionDataListType; @@ -371,6 +378,8 @@ public: typedef SymbolDataListType::const_iterator const_symbol_iterator; typedef SymbolDataListType::iterator symbol_iterator; + typedef std::vector<IndirectSymbolData>::iterator indirect_symbol_iterator; + private: MCAssembler(const MCAssembler&); // DO NOT IMPLEMENT void operator=(const MCAssembler&); // DO NOT IMPLEMENT @@ -381,6 +390,8 @@ private: iplist<MCSymbolData> Symbols; + std::vector<IndirectSymbolData> IndirectSymbols; + private: /// LayoutSection - Assign offsets and sizes to the fragments in the section /// \arg SD, and update the section size. The section file offset should @@ -432,6 +443,27 @@ public: size_t symbol_size() const { return Symbols.size(); } /// @} + /// @name Indirect Symbol List Access + /// @{ + + // FIXME: This is a total hack, this should not be here. Once things are + // factored so that the streamer has direct access to the .o writer, it can + // disappear. + std::vector<IndirectSymbolData> &getIndirectSymbols() { + return IndirectSymbols; + } + + indirect_symbol_iterator indirect_symbol_begin() { + return IndirectSymbols.begin(); + } + + indirect_symbol_iterator indirect_symbol_end() { + return IndirectSymbols.end(); + } + + size_t indirect_symbol_size() const { return IndirectSymbols.size(); } + + /// @} }; } // end namespace llvm diff --git a/lib/MC/MCAssembler.cpp b/lib/MC/MCAssembler.cpp index 9315422..22e0c0d 100644 --- a/lib/MC/MCAssembler.cpp +++ b/lib/MC/MCAssembler.cpp @@ -311,12 +311,68 @@ public: Write32(0); // FIXME: Value } + void BindIndirectSymbols(MCAssembler &Asm) { + // This is the point where 'as' creates actual symbols for indirect symbols + // (in the following two passes). It would be easier for us to do this + // sooner when we see the attribute, but that makes getting the order in the + // symbol table much more complicated than it is worth. + // + // FIXME: Revisit this when the dust settles. + + // FIXME: This should not be needed. + DenseMap<MCSymbol*, MCSymbolData *> SymbolMap; + + for (MCAssembler::symbol_iterator it = Asm.symbol_begin(), + ie = Asm.symbol_end(); it != ie; ++it) + SymbolMap[&it->getSymbol()] = it; + + // Bind non lazy symbol pointers first. + for (MCAssembler::indirect_symbol_iterator it = Asm.indirect_symbol_begin(), + ie = Asm.indirect_symbol_end(); it != ie; ++it) { + // FIXME: cast<> support! + const MCSectionMachO &Section = + static_cast<const MCSectionMachO&>(it->SectionData->getSection()); + + unsigned Type = + Section.getTypeAndAttributes() & MCSectionMachO::SECTION_TYPE; + if (Type != MCSectionMachO::S_NON_LAZY_SYMBOL_POINTERS) + continue; + + MCSymbolData *&Entry = SymbolMap[it->Symbol]; + if (!Entry) + Entry = new MCSymbolData(*it->Symbol, 0, 0, &Asm); + } + + // Then lazy symbol pointers and symbol stubs. + for (MCAssembler::indirect_symbol_iterator it = Asm.indirect_symbol_begin(), + ie = Asm.indirect_symbol_end(); it != ie; ++it) { + // FIXME: cast<> support! + const MCSectionMachO &Section = + static_cast<const MCSectionMachO&>(it->SectionData->getSection()); + + unsigned Type = + Section.getTypeAndAttributes() & MCSectionMachO::SECTION_TYPE; + if (Type != MCSectionMachO::S_LAZY_SYMBOL_POINTERS && + Type != MCSectionMachO::S_SYMBOL_STUBS) + continue; + + MCSymbolData *&Entry = SymbolMap[it->Symbol]; + if (!Entry) { + Entry = new MCSymbolData(*it->Symbol, 0, 0, &Asm); + + // Set the symbol type to undefined lazy, but only on construction. + // + // FIXME: Do not hardcode. + Entry->setFlags(Entry->getFlags() | 0x0001); + } + } + } + /// ComputeSymbolTable - Compute the symbol table data /// /// \param StringTable [out] - The string table data. /// \param StringIndexMap [out] - Map from symbol names to offsets in the /// string table. - void ComputeSymbolTable(MCAssembler &Asm, SmallString<256> &StringTable, std::vector<MachSymbolData> &LocalSymbolData, std::vector<MachSymbolData> &ExternalSymbolData, @@ -414,6 +470,8 @@ public: void WriteObject(MCAssembler &Asm) { unsigned NumSections = Asm.size(); + BindIndirectSymbols(Asm); + // Compute symbol table information. SmallString<256> StringTable; std::vector<MachSymbolData> LocalSymbolData; @@ -467,22 +525,32 @@ public: // Write the symbol table load command, if used. if (NumSymbols) { - // The string table is written after all the section data. - uint64_t SymbolTableOffset = SectionDataStartOffset + SectionDataSize; - uint64_t StringTableOffset = - SymbolTableOffset + NumSymbols * Nlist32Size; - WriteSymtabLoadCommand(SymbolTableOffset, NumSymbols, - StringTableOffset, StringTable.size()); - unsigned FirstLocalSymbol = 0; unsigned NumLocalSymbols = LocalSymbolData.size(); unsigned FirstExternalSymbol = FirstLocalSymbol + NumLocalSymbols; unsigned NumExternalSymbols = ExternalSymbolData.size(); unsigned FirstUndefinedSymbol = FirstExternalSymbol + NumExternalSymbols; unsigned NumUndefinedSymbols = UndefinedSymbolData.size(); - // FIXME: Get correct symbol indices and counts for indirect symbols. - unsigned IndirectSymbolOffset = 0; - unsigned NumIndirectSymbols = 0; + unsigned NumIndirectSymbols = Asm.indirect_symbol_size(); + unsigned NumSymTabSymbols = + NumLocalSymbols + NumExternalSymbols + NumUndefinedSymbols; + uint64_t IndirectSymbolSize = NumIndirectSymbols * 4; + uint64_t IndirectSymbolOffset = 0; + + // If used, the indirect symbols are written after the section data. + if (NumIndirectSymbols) + IndirectSymbolOffset = SectionDataStartOffset + SectionDataSize; + + // The symbol table is written after the indirect symbol data. + uint64_t SymbolTableOffset = + SectionDataStartOffset + SectionDataSize + IndirectSymbolSize; + + // The string table is written after symbol table. + uint64_t StringTableOffset = + SymbolTableOffset + NumSymTabSymbols * Nlist32Size; + WriteSymtabLoadCommand(SymbolTableOffset, NumSymTabSymbols, + StringTableOffset, StringTable.size()); + WriteDysymtabLoadCommand(FirstLocalSymbol, NumLocalSymbols, FirstExternalSymbol, NumExternalSymbols, FirstUndefinedSymbol, NumUndefinedSymbols, @@ -495,9 +563,13 @@ public: // Write the symbol table data, if used. if (NumSymbols) { - // FIXME: Check that offsets match computed ones. + // Write the indirect symbol entries. + // + // FIXME: We need the symbol index map for this. + for (unsigned i = 0, e = Asm.indirect_symbol_size(); i != e; ++i) + Write32(0); - // FIXME: Some of these are ordered by name to help the linker. + // FIXME: Check that offsets match computed ones. // Write the symbol table entries. for (unsigned i = 0, e = LocalSymbolData.size(); i != e; ++i) diff --git a/lib/MC/MCMachOStreamer.cpp b/lib/MC/MCMachOStreamer.cpp index 9d60e3e..f49f6e0 100644 --- a/lib/MC/MCMachOStreamer.cpp +++ b/lib/MC/MCMachOStreamer.cpp @@ -165,6 +165,16 @@ void MCMachOStreamer::EmitAssignment(MCSymbol *Symbol, void MCMachOStreamer::EmitSymbolAttribute(MCSymbol *Symbol, SymbolAttr Attribute) { + // Indirect symbols are handled differently, to match how 'as' handles + // them. This makes writing matching .o files easier. + if (Attribute == MCStreamer::IndirectSymbol) { + IndirectSymbolData ISD; + ISD.Symbol = Symbol; + ISD.SectionData = CurSectionData; + Assembler.getIndirectSymbols().push_back(ISD); + return; + } + // Adding a symbol attribute always introduces the symbol, note that an // important side effect of calling getSymbolData here is to register the // symbol with the assembler. @@ -177,6 +187,7 @@ void MCMachOStreamer::EmitSymbolAttribute(MCSymbol *Symbol, // In the future it might be worth trying to make these operations more well // defined. switch (Attribute) { + case MCStreamer::IndirectSymbol: case MCStreamer::Hidden: case MCStreamer::Internal: case MCStreamer::Protected: @@ -195,10 +206,6 @@ void MCMachOStreamer::EmitSymbolAttribute(MCSymbol *Symbol, SD.setFlags(SD.getFlags() | SF_ReferenceTypeUndefinedLazy); break; - case MCStreamer::IndirectSymbol: - llvm_unreachable("FIXME: Not yet implemented!"); - break; - // Since .reference sets the no dead strip bit, it is equivalent to // .no_dead_strip in practice. case MCStreamer::Reference: |