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