1 //===- SizeTraits.h -------------------------------------------------------===//
2 //
3 //                     The MCLinker Project
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 #ifndef MCLD_ADT_SIZETRAITS_H_
10 #define MCLD_ADT_SIZETRAITS_H_
11 
12 #include <llvm/Support/DataTypes.h>
13 #include <llvm/Support/ELF.h>
14 
15 namespace mcld {
16 
17 template <size_t SIZE>
18 class SizeTraits;
19 
20 template <>
21 class SizeTraits<32> {
22  public:
23   typedef uint32_t Address;
24   typedef uint32_t Offset;
25   typedef uint32_t Word;
26   typedef int32_t SWord;
27 };
28 
29 template <>
30 class SizeTraits<64> {
31  public:
32   typedef uint64_t Address;
33   typedef uint64_t Offset;
34   typedef uint64_t Word;
35   typedef int64_t SWord;
36 };
37 
38 // FIXME: move this to mcld internal ELF header file?
39 template <size_t SIZE>
40 class ELFSizeTraits;
41 
42 template <>
43 class ELFSizeTraits<32> {
44  public:
45   typedef llvm::ELF::Elf32_Addr Addr;  // Program address
46   typedef llvm::ELF::Elf32_Off Off;    // File offset
47   typedef llvm::ELF::Elf32_Half Half;
48   typedef llvm::ELF::Elf32_Word Word;
49   typedef llvm::ELF::Elf32_Sword Sword;
50 
51   typedef llvm::ELF::Elf32_Ehdr Ehdr;
52   typedef llvm::ELF::Elf32_Shdr Shdr;
53   typedef llvm::ELF::Elf32_Sym Sym;
54   typedef llvm::ELF::Elf32_Rel Rel;
55   typedef llvm::ELF::Elf32_Rela Rela;
56   typedef llvm::ELF::Elf32_Phdr Phdr;
57   typedef llvm::ELF::Elf32_Dyn Dyn;
58 };
59 
60 template <>
61 class ELFSizeTraits<64> {
62  public:
63   typedef llvm::ELF::Elf64_Addr Addr;
64   typedef llvm::ELF::Elf64_Off Off;
65   typedef llvm::ELF::Elf64_Half Half;
66   typedef llvm::ELF::Elf64_Word Word;
67   typedef llvm::ELF::Elf64_Sword Sword;
68   typedef llvm::ELF::Elf64_Xword Xword;
69   typedef llvm::ELF::Elf64_Sxword Sxword;
70 
71   typedef llvm::ELF::Elf64_Ehdr Ehdr;
72   typedef llvm::ELF::Elf64_Shdr Shdr;
73   typedef llvm::ELF::Elf64_Sym Sym;
74   typedef llvm::ELF::Elf64_Rel Rel;
75   typedef llvm::ELF::Elf64_Rela Rela;
76   typedef llvm::ELF::Elf64_Phdr Phdr;
77   typedef llvm::ELF::Elf64_Dyn Dyn;
78 };
79 
80 /// alignAddress - helper function to align an address with given alignment
81 /// constraint
82 ///
83 /// @param pAddr - the address to be aligned
84 /// @param pAlignConstraint - the alignment used to align the given address
alignAddress(uint64_t & pAddr,uint64_t pAlignConstraint)85 inline void alignAddress(uint64_t& pAddr, uint64_t pAlignConstraint) {
86   if (pAlignConstraint != 0)
87     pAddr = (pAddr + pAlignConstraint - 1) & ~(pAlignConstraint - 1);
88 }
89 
90 template <size_t Constraint>
91 uint64_t Align(uint64_t pAddress);
92 
93 template <>
94 inline uint64_t Align<32>(uint64_t pAddress) {
95   return (pAddress + 0x1F) & (~0x1F);
96 }
97 
98 template <>
99 inline uint64_t Align<64>(uint64_t pAddress) {
100   return (pAddress + 0x3F) & (~0x3F);
101 }
102 
103 #ifdef bswap16
104 #undef bswap16
105 #endif
106 #ifdef bswap32
107 #undef bswap32
108 #endif
109 #ifdef bswap64
110 #undef bswap64
111 #endif
112 
113 /// bswap16 - byte swap 16-bit version
114 /// @ref binary utilities - elfcpp_swap
bswap16(uint16_t pData)115 inline uint16_t bswap16(uint16_t pData) {
116   return ((pData >> 8) & 0xFF) | ((pData & 0xFF) << 8);
117 }
118 
119 /// bswap32 - byte swap 32-bit version
120 /// @ref elfcpp_swap
bswap32(uint32_t pData)121 inline uint32_t bswap32(uint32_t pData) {
122   return (((pData & 0xFF000000) >> 24) | ((pData & 0x00FF0000) >> 8) |
123           ((pData & 0x0000FF00) << 8) | ((pData & 0x000000FF) << 24));
124 }
125 
126 /// bswap64 - byte swap 64-bit version
127 /// @ref binary utilities - elfcpp_swap
bswap64(uint64_t pData)128 inline uint64_t bswap64(uint64_t pData) {
129   return (((pData & 0xFF00000000000000ULL) >> 56) |
130           ((pData & 0x00FF000000000000ULL) >> 40) |
131           ((pData & 0x0000FF0000000000ULL) >> 24) |
132           ((pData & 0x000000FF00000000ULL) >> 8) |
133           ((pData & 0x00000000FF000000ULL) << 8) |
134           ((pData & 0x0000000000FF0000ULL) << 24) |
135           ((pData & 0x000000000000FF00ULL) << 40) |
136           ((pData & 0x00000000000000FFULL) << 56));
137 }
138 
139 template <size_t SIZE>
140 typename SizeTraits<SIZE>::Word bswap(typename SizeTraits<SIZE>::Word pData);
141 
142 template <>
143 inline SizeTraits<32>::Word bswap<32>(SizeTraits<32>::Word pData) {
144   return bswap32(pData);
145 }
146 
147 template <>
148 inline SizeTraits<64>::Word bswap<64>(SizeTraits<64>::Word pData) {
149   return bswap64(pData);
150 }
151 
152 template <size_t WIDTH>
signExtend(uint64_t pVal)153 inline uint64_t signExtend(uint64_t pVal) {
154   uint64_t mask = (~((uint64_t)0)) >> (64 - WIDTH);
155   uint64_t sign_bit = 1 << (WIDTH - 1);
156 
157   return ((pVal & mask) ^ sign_bit) - sign_bit;
158 }
159 
160 template <>
161 inline uint64_t signExtend<64>(uint64_t pVal) {
162   return pVal;
163 }
164 
165 template <size_t SizeOfStr, typename FieldType>
166 class StringSizerHelper {
167  private:
168   char FIELD_TOO_SMALL[SizeOfStr <= FieldType(~0U) ? 1 : -1];
169 
170  public:
171   enum { Size = SizeOfStr };
172 };
173 
174 #define STR_SIZE(str, fieldTy) StringSizerHelper<sizeof(str) - 1, fieldTy>::Size
175 
176 }  // namespace mcld
177 
178 #endif  // MCLD_ADT_SIZETRAITS_H_
179