| //===- GNULDBackend.h -----------------------------------------------------===// |
| // |
| // The MCLinker Project |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| #ifndef MCLD_TARGET_GNU_LDBACKEND_H |
| #define MCLD_TARGET_GNU_LDBACKEND_H |
| #ifdef ENABLE_UNITTEST |
| #include <gtest.h> |
| #endif |
| |
| #include <llvm/Support/ELF.h> |
| #include <mcld/ADT/HashTable.h> |
| #include <mcld/ADT/HashEntry.h> |
| #include <mcld/LD/EhFrameHdr.h> |
| #include <mcld/LD/ELFDynObjFileFormat.h> |
| #include <mcld/LD/ELFDynObjReader.h> |
| #include <mcld/LD/ELFDynObjWriter.h> |
| #include <mcld/LD/ELFExecFileFormat.h> |
| #include <mcld/LD/ELFExecWriter.h> |
| #include <mcld/LD/ELFObjectReader.h> |
| #include <mcld/LD/ELFObjectWriter.h> |
| #include <mcld/LD/ELFSegment.h> |
| #include <mcld/LD/ELFSegmentFactory.h> |
| #include <mcld/LD/GNUArchiveReader.h> |
| #include <mcld/Support/GCFactory.h> |
| #include <mcld/Target/ELFDynamic.h> |
| #include <mcld/Target/TargetLDBackend.h> |
| |
| namespace mcld |
| { |
| |
| struct SymCompare |
| { |
| bool operator()(const LDSymbol* X, const LDSymbol* Y) const |
| { return (X==Y); } |
| }; |
| |
| struct PtrHash |
| { |
| size_t operator()(const LDSymbol* pKey) const |
| { |
| return (unsigned((uintptr_t)pKey) >> 4) ^ |
| (unsigned((uintptr_t)pKey) >> 9); |
| } |
| }; |
| |
| class MCLDInfo; |
| class Layout; |
| class SymbolCategory; |
| |
| /** \class GNULDBackend |
| * \brief GNULDBackend provides a common interface for all GNU Unix-OS |
| * LDBackend. |
| */ |
| class GNULDBackend : public TargetLDBackend |
| { |
| protected: |
| GNULDBackend(); |
| |
| public: |
| virtual ~GNULDBackend(); |
| |
| // ----- readers/writers ----- // |
| bool initArchiveReader(MCLinker& pLinker, |
| MCLDInfo& pInfo, |
| MemoryAreaFactory& pMemAreaFactory); |
| bool initObjectReader(MCLinker& pLinker); |
| bool initDynObjReader(MCLinker& pLinker); |
| bool initObjectWriter(MCLinker& pLinker); |
| bool initDynObjWriter(MCLinker& pLinker); |
| bool initExecWriter(MCLinker& pLinker); |
| |
| GNUArchiveReader *getArchiveReader(); |
| const GNUArchiveReader *getArchiveReader() const; |
| |
| ELFObjectReader *getObjectReader(); |
| const ELFObjectReader *getObjectReader() const; |
| |
| ELFDynObjReader *getDynObjReader(); |
| const ELFDynObjReader *getDynObjReader() const; |
| |
| ELFObjectWriter *getObjectWriter(); |
| const ELFObjectWriter *getObjectWriter() const; |
| |
| ELFDynObjWriter *getDynObjWriter(); |
| const ELFDynObjWriter *getDynObjWriter() const; |
| |
| ELFExecWriter *getExecWriter(); |
| const ELFExecWriter *getExecWriter() const; |
| |
| // ----- output sections ----- // |
| /// initExecSections - initialize sections of the output executable file. |
| bool initExecSections(MCLinker& pMCLinker); |
| |
| /// initDynObjSections - initialize sections of the output shared object. |
| bool initDynObjSections(MCLinker& pMCLinker); |
| |
| /// getOutputFormat - get the sections of the output file. |
| ELFFileFormat* getOutputFormat(const Output& pOutput); |
| const ELFFileFormat* getOutputFormat(const Output& pOutput) const; |
| |
| ELFDynObjFileFormat* getDynObjFileFormat(); |
| const ELFDynObjFileFormat* getDynObjFileFormat() const; |
| |
| ELFExecFileFormat* getExecFileFormat(); |
| const ELFExecFileFormat* getExecFileFormat() const; |
| |
| // ----- target symbols ----- // |
| /// initStandardSymbols - initialize standard symbols. |
| /// Some section symbols is undefined in input object, and linkers must set |
| /// up its value. Take __init_array_begin for example. This symbol is an |
| /// undefined symbol in input objects. MCLinker must finalize its value |
| /// to the begin of the .init_array section, then relocation enties to |
| /// __init_array_begin can be applied without emission of "undefined |
| /// reference to `__init_array_begin'". |
| bool initStandardSymbols(MCLinker& pLinker, const Output& pOutput); |
| |
| /// finalizeSymbol - Linker checks pSymbol.reserved() if it's not zero, |
| /// then it will ask backend to finalize the symbol value. |
| /// @return ture - if backend set the symbol value sucessfully |
| /// @return false - if backend do not recognize the symbol |
| bool finalizeSymbols(MCLinker& pLinker, const Output& pOutput) { |
| return (finalizeStandardSymbols(pLinker, pOutput) && |
| finalizeTargetSymbols(pLinker, pOutput)); |
| } |
| |
| /// finalizeStandardSymbols - set the value of standard symbols |
| virtual bool finalizeStandardSymbols(MCLinker& pLinker, |
| const Output& pOutput); |
| |
| /// finalizeTargetSymbols - set the value of target symbols |
| virtual bool finalizeTargetSymbols(MCLinker& pLinker, |
| const Output& pOutput) = 0; |
| |
| size_t sectionStartOffset() const; |
| |
| /// The return value of machine() it the same as e_machine in the ELF header*/ |
| virtual uint32_t machine() const = 0; |
| |
| /// ELFVersion - the value of e_ident[EI_VERSION] |
| virtual uint8_t ELFVersion() const |
| { return llvm::ELF::EV_CURRENT; } |
| |
| /// OSABI - the value of e_ident[EI_OSABI] |
| virtual uint8_t OSABI() const = 0; |
| |
| /// ABIVersion - the value of e_ident[EI_ABIVRESION] |
| virtual uint8_t ABIVersion() const = 0; |
| |
| /// flags - the value of ElfXX_Ehdr::e_flags |
| virtual uint64_t flags() const = 0; |
| |
| /// entry - the symbol name of the entry point |
| virtual const char* entry() const |
| { return "_start"; } |
| |
| /// dyld - the name of the default dynamic linker |
| /// target may override this function if needed. |
| /// @ref gnu ld, bfd/elf32-i386.c:521 |
| virtual const char* dyld() const |
| { return "/usr/lib/libc.so.1"; } |
| |
| /// defaultTextSegmentAddr - target should specify its own default start address |
| /// of the text segment. esp. for exec. |
| virtual uint64_t defaultTextSegmentAddr() const |
| { return 0x0; } |
| |
| /// segmentStartAddr - this function returns the start address of the segment |
| uint64_t segmentStartAddr(const Output& pOutput, |
| const MCLDInfo& pInfo) const; |
| |
| /// sizeNamePools - compute the size of regular name pools |
| /// In ELF executable files, regular name pools are .symtab, .strtab., |
| /// .dynsym, .dynstr, and .hash |
| virtual void sizeNamePools(const Output& pOutput, |
| const SymbolCategory& pSymbols, |
| const MCLDInfo& pLDInfo); |
| |
| /// emitSectionData - emit target-dependent section data |
| virtual uint64_t emitSectionData(const Output& pOutput, |
| const LDSection& pSection, |
| const MCLDInfo& pInfo, |
| const Layout& pLayout, |
| MemoryRegion& pRegion) const = 0; |
| |
| /// emitRegNamePools - emit regular name pools - .symtab, .strtab |
| virtual void emitRegNamePools(Output& pOutput, |
| SymbolCategory& pSymbols, |
| const Layout& pLayout, |
| const MCLDInfo& pLDInfo); |
| |
| /// emitNamePools - emit dynamic name pools - .dyntab, .dynstr, .hash |
| virtual void emitDynNamePools(Output& pOutput, |
| SymbolCategory& pSymbols, |
| const Layout& pLayout, |
| const MCLDInfo& pLDInfo); |
| |
| /// sizeInterp - compute the size of program interpreter's name |
| /// In ELF executables, this is the length of dynamic linker's path name |
| virtual void sizeInterp(const Output& pOutput, const MCLDInfo& pLDInfo); |
| |
| /// emitInterp - emit the .interp |
| virtual void emitInterp(Output& pOutput, const MCLDInfo& pLDInfo); |
| |
| /// getSectionOrder - compute the layout order of the section |
| /// Layout calls this function to get the default order of the pSectHdr. |
| /// If the pSectHdr.type() is LDFileFormat::Target, then getSectionOrder() |
| /// will call getTargetSectionOrder(). |
| /// |
| /// If targets favors certain order for general sections, please override |
| /// this function. |
| /// |
| /// @see getTargetSectionOrder |
| virtual unsigned int getSectionOrder(const Output& pOutput, |
| const LDSection& pSectHdr, |
| const MCLDInfo& pInfo) const; |
| |
| /// getTargetSectionOrder - compute the layout order of target section |
| /// If the target favors certain order for the given gSectHdr, please |
| /// override this function. |
| /// |
| /// By default, this function returns the maximun order, and pSectHdr |
| /// will be the last section to be laid out. |
| virtual unsigned int |
| getTargetSectionOrder(const Output& pOutput, |
| const LDSection& pSectHdr, |
| const MCLDInfo& pInfo) const |
| { return (unsigned int)-1; } |
| |
| /// numOfSegments - return the number of segments |
| /// if the target favors other ways to emit program header, please override |
| /// this function |
| virtual unsigned int numOfSegments() const |
| { return m_ELFSegmentTable.size(); } |
| |
| /// elfSegmentTable - return the reference of the elf segment table |
| ELFSegmentFactory& elfSegmentTable() |
| { return m_ELFSegmentTable; } |
| |
| /// elfSegmentTable - return the reference of the elf segment table |
| const ELFSegmentFactory& elfSegmentTable() const |
| { return m_ELFSegmentTable; } |
| |
| /// commonPageSize - the common page size of the target machine, and we set it |
| /// to 4K here. If target favors the different size, please override this |
| /// function |
| virtual uint64_t commonPageSize(const MCLDInfo& pInfo) const; |
| |
| /// abiPageSize - the abi page size of the target machine, and we set it to 4K |
| /// here. If target favors the different size, please override this function |
| virtual uint64_t abiPageSize(const MCLDInfo& pInfo) const; |
| |
| /// getSymbolIdx - get the symbol index of ouput symbol table |
| size_t getSymbolIdx(LDSymbol* pSymbol) const; |
| |
| /// isDefaultExecStack - target should specify whether the stack is default |
| /// executable. If target favors another choice, please override this function |
| virtual bool isDefaultExecStack() const |
| { return true; } |
| |
| /// allocateCommonSymbols - allocate common symbols in the corresponding |
| /// sections. |
| /// Different concrete target backend may overlap this function. |
| virtual bool allocateCommonSymbols(const MCLDInfo& pLDInfo, MCLinker& pLinker) const; |
| |
| /// isSymbolPreemtible - whether the symbol can be preemted by other |
| /// link unit |
| /// @ref Google gold linker, symtab.h:551 |
| bool isSymbolPreemptible(const ResolveInfo& pSym, |
| const MCLDInfo& pLDInfo, |
| const Output& pOutput) const; |
| |
| /// symbolNeedsDynRel - return whether the symbol needs a dynamic relocation |
| /// @ref Google gold linker, symtab.h:645 |
| bool symbolNeedsDynRel(const ResolveInfo& pSym, |
| bool pSymHasPLT, |
| const MCLDInfo& pLDInfo, |
| const Output& pOutput, |
| bool isAbsReloc) const; |
| |
| protected: |
| uint64_t getSymbolSize(const LDSymbol& pSymbol) const; |
| |
| uint64_t getSymbolInfo(const LDSymbol& pSymbol) const; |
| |
| uint64_t getSymbolValue(const LDSymbol& pSymbol) const; |
| |
| uint64_t getSymbolShndx(const LDSymbol& pSymbol, const Layout& pLayout) const; |
| |
| /// getHashBucketCount - calculate hash bucket count. |
| /// @ref Google gold linker, dynobj.cc:791 |
| static unsigned getHashBucketCount(unsigned pNumOfSymbols, bool pIsGNUStyle); |
| |
| /// isDynamicSymbol |
| /// @ref Google gold linker: symtab.cc:311 |
| static bool isDynamicSymbol(const LDSymbol& pSymbol, const Output& pOutput); |
| |
| /// isOutputPIC - return whether the output is position-independent |
| bool isOutputPIC(const Output& pOutput, const MCLDInfo& pInfo) const; |
| |
| /// isStaticLink - return whether we're doing static link |
| bool isStaticLink(const Output& pOutput, const MCLDInfo& pInfo) const; |
| |
| /// symbolNeedsPLT - return whether the symbol needs a PLT entry |
| /// @ref Google gold linker, symtab.h:596 |
| bool symbolNeedsPLT(const ResolveInfo& pSym, |
| const MCLDInfo& pLDInfo, |
| const Output& pOutput) const; |
| |
| /// symbolNeedsCopyReloc - return whether the symbol needs a copy relocation |
| bool symbolNeedsCopyReloc(const Layout& pLayout, |
| const Relocation& pReloc, |
| const ResolveInfo& pSym, |
| const MCLDInfo& pLDInfo, |
| const Output& pOutput) const; |
| |
| private: |
| /// createProgramHdrs - base on output sections to create the program headers |
| void createProgramHdrs(Output& pOutput, |
| const MCLDInfo& pInfo); |
| |
| /// setupProgramHdrs - set up the attributes of segments |
| /// (i.e., offset, addresses, file/mem size, flag, and alignment) |
| void setupProgramHdrs(const Output& pOutput, const MCLDInfo& pInfo); |
| |
| /// getSegmentFlag - give a section flag and return the corresponding segment |
| /// flag |
| inline uint32_t getSegmentFlag(const uint32_t pSectionFlag) |
| { |
| uint32_t flag = llvm::ELF::PF_R; |
| if (0 != (pSectionFlag & llvm::ELF::SHF_WRITE)) |
| flag |= llvm::ELF::PF_W; |
| if (0 != (pSectionFlag & llvm::ELF::SHF_EXECINSTR)) |
| flag |= llvm::ELF::PF_X; |
| return flag; |
| } |
| |
| /// createGNUStackInfo - create an output GNU stack section or segment if needed |
| void createGNUStackInfo(const Output& pOutput, |
| const MCLDInfo& pInfo, |
| MCLinker& pLinker); |
| |
| /// preLayout - Backend can do any needed modification before layout |
| void preLayout(const Output& pOutput, |
| const MCLDInfo& pInfo, |
| MCLinker& pLinker); |
| |
| /// postLayout -Backend can do any needed modification after layout |
| void postLayout(const Output& pOutput, |
| const MCLDInfo& pInfo, |
| MCLinker& pLinker); |
| |
| /// preLayout - Backend can do any needed modification before layout |
| virtual void doPreLayout(const Output& pOutput, |
| const MCLDInfo& pInfo, |
| MCLinker& pLinker) = 0; |
| |
| /// postLayout -Backend can do any needed modification after layout |
| virtual void doPostLayout(const Output& pOutput, |
| const MCLDInfo& pInfo, |
| MCLinker& pLinker) = 0; |
| |
| /// postProcessing - Backend can do any needed modification in the final stage |
| void postProcessing(const Output& pOutput, |
| const MCLDInfo& pInfo, |
| MCLinker& pLinker); |
| |
| /// dynamic - the dynamic section of the target machine. |
| virtual ELFDynamic& dynamic() = 0; |
| |
| /// dynamic - the dynamic section of the target machine. |
| virtual const ELFDynamic& dynamic() const = 0; |
| |
| protected: |
| // Based on Kind in LDFileFormat to define basic section orders for ELF, and |
| // refer gold linker to add more enumerations to handle Regular and BSS kind |
| enum SectionOrder { |
| SHO_INTERP = 1, // .interp |
| SHO_RO_NOTE, // .note.ABI-tag, .note.gnu.build-id |
| SHO_NAMEPOOL, // *.hash, .dynsym, .dynstr |
| SHO_RELOCATION, // .rel.*, .rela.* |
| SHO_REL_PLT, // .rel.plt should come after other .rel.* |
| SHO_INIT, // .init |
| SHO_PLT, // .plt |
| SHO_TEXT, // .text |
| SHO_FINI, // .fini |
| SHO_RO, // .rodata |
| SHO_EXCEPTION, // .eh_frame_hdr, .eh_frame, .gcc_except_table |
| SHO_TLS_DATA, // .tdata |
| SHO_TLS_BSS, // .tbss |
| SHO_RELRO_LOCAL, // .data.rel.ro.local |
| SHO_RELRO, // .data.rel.ro, |
| SHO_RELRO_LAST, // for x86 to adjust .got if needed |
| SHO_NON_RELRO_FIRST, // for x86 to adjust .got.plt if needed |
| SHO_DATA, // .data |
| SHO_LARGE_DATA, // .ldata |
| SHO_RW_NOTE, // |
| SHO_SMALL_DATA, // .sdata |
| SHO_SMALL_BSS, // .sbss |
| SHO_BSS, // .bss |
| SHO_LARGE_BSS, // .lbss |
| SHO_UNDEFINED = ~(0U) // default order |
| }; |
| |
| typedef HashEntry<LDSymbol*, size_t, SymCompare> HashEntryType; |
| typedef HashTable<HashEntryType, PtrHash, EntryFactory<HashEntryType> > HashTableType; |
| |
| protected: |
| // ----- readers and writers ----- // |
| GNUArchiveReader* m_pArchiveReader; |
| ELFObjectReader* m_pObjectReader; |
| ELFDynObjReader* m_pDynObjReader; |
| ELFObjectWriter* m_pObjectWriter; |
| ELFDynObjWriter* m_pDynObjWriter; |
| ELFExecWriter* m_pExecWriter; |
| |
| // ----- file formats ----- // |
| ELFDynObjFileFormat* m_pDynObjFileFormat; |
| ELFExecFileFormat* m_pExecFileFormat; |
| |
| // ELF segment factory |
| ELFSegmentFactory m_ELFSegmentTable; |
| |
| // map the LDSymbol to its index in the output symbol table |
| HashTableType* m_pSymIndexMap; |
| |
| // section .eh_frame_hdr |
| EhFrameHdr* m_pEhFrameHdr; |
| |
| // ----- standard symbols ----- // |
| // section symbols |
| LDSymbol* f_pPreInitArrayStart; |
| LDSymbol* f_pPreInitArrayEnd; |
| LDSymbol* f_pInitArrayStart; |
| LDSymbol* f_pInitArrayEnd; |
| LDSymbol* f_pFiniArrayStart; |
| LDSymbol* f_pFiniArrayEnd; |
| LDSymbol* f_pStack; |
| |
| // segment symbols |
| LDSymbol* f_pExecutableStart; |
| LDSymbol* f_pEText; |
| LDSymbol* f_p_EText; |
| LDSymbol* f_p__EText; |
| LDSymbol* f_pEData; |
| LDSymbol* f_p_EData; |
| LDSymbol* f_pBSSStart; |
| LDSymbol* f_pEnd; |
| LDSymbol* f_p_End; |
| }; |
| |
| } // namespace of mcld |
| |
| #endif |
| |