| //===- lib/ReaderWriter/ELF/CreateELF.h -----------------------------------===// |
| // |
| // The LLVM Linker |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| /// |
| /// \file |
| /// \brief This file provides a simple way to create an object templated on |
| /// ELFType depending on the runtime type needed. |
| /// |
| //===----------------------------------------------------------------------===// |
| #ifndef LLD_READER_WRITER_ELF_CREATE_ELF_H |
| #define LLD_READER_WRITER_ELF_CREATE_ELF_H |
| |
| #include "llvm/Object/ELF.h" |
| #include "llvm/Support/Compiler.h" |
| |
| namespace { |
| using llvm::object::ELFType; |
| |
| /// \func createELF |
| /// \brief Create an object depending on the runtime attributes and alignment |
| /// of an ELF file. |
| /// |
| /// \param Traits |
| /// Traits::result_type must be a type convertable from what create returns. |
| /// Traits::create must be a template function which takes an ELFType and |
| /// returns something convertable to Traits::result_type. |
| /// |
| /// \param ident pair of EI_CLASS and EI_DATA. |
| /// \param maxAlignment the maximum alignment of the file. |
| /// \param args arguments forwarded to CreateELFTraits<T>::create. |
| |
| #define LLVM_CREATE_ELF_CreateELFTraits(endian, align, is64, ...) \ |
| Traits::template create<ELFType<llvm::support::endian, align, is64>>( \ |
| __VA_ARGS__); |
| |
| #if !LLVM_IS_UNALIGNED_ACCESS_FAST |
| # define LLVM_CREATE_ELF_MaxAlignCheck(normal, low, endian, is64, ...) \ |
| if (maxAlignment >= normal) \ |
| return LLVM_CREATE_ELF_CreateELFTraits(endian, normal, is64, __VA_ARGS__) \ |
| else if (maxAlignment >= low) \ |
| return LLVM_CREATE_ELF_CreateELFTraits(endian, low, is64, __VA_ARGS__) \ |
| else \ |
| llvm_unreachable("Invalid alignment for ELF file!"); |
| #else |
| # define LLVM_CREATE_ELF_MaxAlignCheck(normal, low, endian, is64, ...) \ |
| if (maxAlignment >= low) \ |
| return LLVM_CREATE_ELF_CreateELFTraits(endian, low, is64, __VA_ARGS__) \ |
| else \ |
| llvm_unreachable("Invalid alignment for ELF file!"); |
| #endif |
| |
| #define LLVM_CREATE_ELF_IMPL(...) \ |
| if (ident.first == llvm::ELF::ELFCLASS32 && \ |
| ident.second == llvm::ELF::ELFDATA2LSB) { \ |
| LLVM_CREATE_ELF_MaxAlignCheck(4, 2, little, false, __VA_ARGS__) \ |
| } else if (ident.first == llvm::ELF::ELFCLASS32 && \ |
| ident.second == llvm::ELF::ELFDATA2MSB) { \ |
| LLVM_CREATE_ELF_MaxAlignCheck(4, 2, big, false, __VA_ARGS__) \ |
| } else if (ident.first == llvm::ELF::ELFCLASS64 && \ |
| ident.second == llvm::ELF::ELFDATA2MSB) { \ |
| LLVM_CREATE_ELF_MaxAlignCheck(8, 2, big, true, __VA_ARGS__) \ |
| } else if (ident.first == llvm::ELF::ELFCLASS64 && \ |
| ident.second == llvm::ELF::ELFDATA2LSB) { \ |
| LLVM_CREATE_ELF_MaxAlignCheck(8, 2, little, true, __VA_ARGS__) \ |
| } \ |
| llvm_unreachable("Invalid ELF type!"); |
| |
| #if LLVM_HAS_VARIADIC_TEMPLATES |
| template <class Traits, class ...Args> |
| typename Traits::result_type createELF( |
| std::pair<unsigned char, unsigned char> ident, std::size_t maxAlignment, |
| Args &&...args) { |
| LLVM_CREATE_ELF_IMPL(std::forward<Args>(args)...) |
| } |
| #else |
| template <class Traits, class T1> |
| typename Traits::result_type createELF( |
| std::pair<unsigned char, unsigned char> ident, std::size_t maxAlignment, |
| T1 &&t1) { |
| LLVM_CREATE_ELF_IMPL(std::forward<T1>(t1)) |
| } |
| |
| template <class Traits, class T1, class T2> |
| typename Traits::result_type createELF( |
| std::pair<unsigned char, unsigned char> ident, std::size_t maxAlignment, |
| T1 &&t1, T2 &&t2) { |
| LLVM_CREATE_ELF_IMPL(std::forward<T1>(t1), std::forward<T2>(t2)) |
| } |
| |
| template <class Traits, class T1, class T2, class T3> |
| typename Traits::result_type createELF( |
| std::pair<unsigned char, unsigned char> ident, std::size_t maxAlignment, |
| T1 &&t1, T2 &&t2, T3 &&t3) { |
| LLVM_CREATE_ELF_IMPL(std::forward<T1>(t1), std::forward<T2>(t2), |
| std::forward<T3>(t3)) |
| } |
| |
| template <class Traits, class T1, class T2, class T3, class T4> |
| typename Traits::result_type createELF( |
| std::pair<unsigned char, unsigned char> ident, std::size_t maxAlignment, |
| T1 &&t1, T2 &&t2, T3 &&t3, T4 &&t4) { |
| LLVM_CREATE_ELF_IMPL(std::forward<T1>(t1), std::forward<T2>(t2), |
| std::forward<T3>(t3), std::forward<T4>(t4)) |
| } |
| |
| #endif // LLVM_HAS_VARIADIC_TEMPLATES |
| } // end anon namespace |
| |
| #undef LLVM_CREATE_ELF_CreateELFTraits |
| #undef LLVM_CREATE_ELF_MaxAlignCheck |
| #undef LLVM_CREATE_ELF_IMPL |
| |
| #endif |