1 /*
2 * Copyright 2011, The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #ifndef ELF_SYMBOL_HXX
18 #define ELF_SYMBOL_HXX
19
20 #include "ELFSectionHeaderTable.h"
21 #include "ELFSection.h"
22 #include "ELFSectionStrTab.h"
23
24 #include "ELFObject.h"
25 #include "ELFSectionHeaderTable.h"
26 #include "ELFSectionProgBits.h"
27 #include "ELFSectionNoBits.h"
28
29 #include "utils/rsl_assert.h"
30 #include "ELF.h"
31
32 template <unsigned Bitwidth>
getName() const33 inline char const *ELFSymbol_CRTP<Bitwidth>::getName() const {
34 ELFSectionHeaderTableTy const &shtab = *owner->getSectionHeaderTable();
35 size_t const index = shtab.getByName(std::string(".strtab"))->getIndex();
36 ELFSectionTy const *section = owner->getSectionByIndex(index);
37 ELFSectionStrTabTy const &strtab =
38 *static_cast<ELFSectionStrTabTy const *>(section);
39 return strtab[getNameIndex()];
40 }
41
42 template <unsigned Bitwidth>
43 template <typename Archiver>
44 inline ELFSymbol<Bitwidth> *
read(Archiver & AR,ELFObjectTy const * owner,size_t index)45 ELFSymbol_CRTP<Bitwidth>::read(Archiver &AR,
46 ELFObjectTy const *owner,
47 size_t index) {
48 if (!AR) {
49 // Archiver is in bad state before calling read function.
50 // Return NULL and do nothing.
51 return 0;
52 }
53
54 llvm::OwningPtr<ELFSymbolTy> sh(new ELFSymbolTy());
55
56 if (!sh->serialize(AR)) {
57 // Unable to read the structure. Return NULL.
58 return 0;
59 }
60
61 if (!sh->isValid()) {
62 // SymTabEntry read from archiver is not valid. Return NULL.
63 return 0;
64 }
65
66 // Set the section header index
67 sh->index = index;
68
69 // Set the owner elf object
70 sh->owner = owner;
71
72 return sh.take();
73 }
74
75 template <unsigned Bitwidth>
print(bool shouldPrintHeader) const76 inline void ELFSymbol_CRTP<Bitwidth>::print(bool shouldPrintHeader) const {
77 using namespace llvm;
78
79 if (shouldPrintHeader) {
80 out() << '\n' << fillformat('=', 79) << '\n';
81 out().changeColor(raw_ostream::WHITE, true);
82 out() << "ELF Symbol Table Entry "
83 << this->getIndex() << '\n';
84 out().resetColor();
85 out() << fillformat('-', 79) << '\n';
86 } else {
87 out() << fillformat('-', 79) << '\n';
88 out().changeColor(raw_ostream::YELLOW, true);
89 out() << "ELF Symbol Table Entry "
90 << this->getIndex() << " : " << '\n';
91 out().resetColor();
92 }
93
94 #define PRINT_LINT(title, value) \
95 out() << format(" %-11s : ", (char const *)(title)) << (value) << '\n'
96 PRINT_LINT("Name", getName() );
97 PRINT_LINT("Type", getTypeStr(getType()) );
98 PRINT_LINT("Bind", getBindingAttributeStr(getBindingAttribute()));
99 PRINT_LINT("Visibility", getVisibilityStr(getVisibility()) );
100 PRINT_LINT("Shtab Index", getSectionIndex() );
101 PRINT_LINT("Value", getValue() );
102 PRINT_LINT("Size", getSize() );
103 #undef PRINT_LINT
104
105 // TODO: Horizontal type or vertical type can use option to decide.
106 #if 0
107 using namespace term::color;
108 using namespace std;
109
110 cout << setw(20) << getName() <<
111 setw(10) << getTypeStr(getType()) <<
112 setw(10) << getBindingAttributeStr(getBindingAttribute()) <<
113 setw(15) << getVisibilityStr(getVisibility()) <<
114 setw(10) << getSectionIndex() <<
115 setw(7) << getValue() <<
116 setw(7) << getSize() <<
117 endl;
118 #endif
119 }
120
121 template <unsigned Bitwidth>
getAddress(int machine,bool autoAlloc) const122 void *ELFSymbol_CRTP<Bitwidth>::getAddress(int machine, bool autoAlloc) const {
123 if (my_addr != 0) {
124 return my_addr;
125 }
126 size_t idx = (size_t)getSectionIndex();
127 switch (getType()) {
128 default:
129 break;
130
131 case STT_OBJECT:
132 switch (idx) {
133 default:
134 {
135 ELFSectionHeaderTableTy const *header =
136 owner->getSectionHeaderTable();
137
138 unsigned section_type = (*header)[idx]->getType();
139
140 rsl_assert((section_type == SHT_PROGBITS ||
141 section_type == SHT_NOBITS) &&
142 "STT_OBJECT with not BITS section.");
143
144 if (section_type == SHT_NOBITS) {
145 // FIXME(logan): This is a workaround for .lcomm directives
146 // bug of LLVM ARM MC code generator. Remove this when the
147 // LLVM bug is fixed.
148
149 size_t align = 16;
150
151 my_addr = const_cast<ELFObjectTy *>(owner)->
152 allocateSHNCommonData((size_t)getSize(), align);
153
154 if (!my_addr) {
155 rsl_assert(0 && "Unable to allocate memory for SHN_COMMON.");
156 abort();
157 }
158 } else {
159 ELFSectionTy const *sec = owner->getSectionByIndex(idx);
160 rsl_assert(sec != 0 && "STT_OBJECT with null section.");
161
162 ELFSectionBitsTy const &st =
163 static_cast<ELFSectionBitsTy const &>(*sec);
164 my_addr =const_cast<unsigned char *>(&st[0] + (off_t)getValue());
165 }
166 }
167 break;
168
169 case SHN_COMMON:
170 {
171 if (!autoAlloc) {
172 return NULL;
173 }
174 #if 0
175 #if _POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600
176 if (posix_memalign(&my_addr,
177 std::max((size_t)getValue(), sizeof(void*)),
178 (size_t)getSize()) != 0) {
179 rsl_assert(0 && "posix_memalign failed.");
180 }
181 #else
182 my_addr = memalign(std::max((size_t)getValue(), sizeof(void *)),
183 (size_t)getSize());
184
185 rsl_assert(my_addr != NULL && "memalign failed.");
186 #endif
187 if (my_addr) {
188 memset(my_addr, '\0', getSize());
189 }
190 #else
191 size_t align = (size_t)getValue();
192 my_addr = const_cast<ELFObjectTy *>(owner)->
193 allocateSHNCommonData((size_t)getSize(), align);
194 if (!my_addr) {
195 rsl_assert(0 && "Unable to allocate memory for SHN_COMMON.");
196 abort();
197 }
198 #endif
199 }
200 break;
201
202 case SHN_UNDEF:
203 if (machine == EM_MIPS && strcmp(getName(), "_gp_disp") == 0) // OK for MIPS
204 break;
205
206 case SHN_ABS:
207 case SHN_XINDEX:
208 rsl_assert(0 && "STT_OBJECT with special st_shndx.");
209 break;
210 }
211 break;
212
213
214 case STT_FUNC:
215 switch (idx) {
216 default:
217 {
218 #ifndef NDEBUG
219 ELFSectionHeaderTableTy const *header =
220 owner->getSectionHeaderTable();
221 rsl_assert((*header)[idx]->getType() == SHT_PROGBITS &&
222 "STT_FUNC with not PROGBITS section.");
223 #endif
224 ELFSectionTy const *sec = owner->getSectionByIndex(idx);
225 rsl_assert(sec != 0 && "STT_FUNC with null section.");
226
227 ELFSectionProgBitsTy const &st =
228 static_cast<ELFSectionProgBitsTy const &>(*sec);
229 my_addr = const_cast<unsigned char *>(&st[0] + (off_t)getValue());
230 }
231 break;
232
233 case SHN_ABS:
234 case SHN_COMMON:
235 case SHN_UNDEF:
236 case SHN_XINDEX:
237 rsl_assert(0 && "STT_FUNC with special st_shndx.");
238 break;
239 }
240 break;
241
242
243 case STT_SECTION:
244 switch (idx) {
245 default:
246 {
247 #ifndef NDEBUG
248 ELFSectionHeaderTableTy const *header =
249 owner->getSectionHeaderTable();
250 rsl_assert(((*header)[idx]->getType() == SHT_PROGBITS ||
251 (*header)[idx]->getType() == SHT_NOBITS) &&
252 "STT_SECTION with not BITS section.");
253 #endif
254 ELFSectionTy const *sec = owner->getSectionByIndex(idx);
255 rsl_assert(sec != 0 && "STT_SECTION with null section.");
256
257 ELFSectionBitsTy const &st =
258 static_cast<ELFSectionBitsTy const &>(*sec);
259 my_addr = const_cast<unsigned char *>(&st[0] + (off_t)getValue());
260 }
261 break;
262
263 case SHN_ABS:
264 case SHN_COMMON:
265 case SHN_UNDEF:
266 case SHN_XINDEX:
267 rsl_assert(0 && "STT_SECTION with special st_shndx.");
268 break;
269 }
270 break;
271
272 case STT_NOTYPE:
273 switch (idx) {
274 default:
275 {
276 #ifndef NDEBUG
277 ELFSectionHeaderTableTy const *header =
278 owner->getSectionHeaderTable();
279 rsl_assert(((*header)[idx]->getType() == SHT_PROGBITS ||
280 (*header)[idx]->getType() == SHT_NOBITS) &&
281 "STT_SECTION with not BITS section.");
282 #endif
283 ELFSectionTy const *sec = owner->getSectionByIndex(idx);
284 rsl_assert(sec != 0 && "STT_SECTION with null section.");
285
286 ELFSectionBitsTy const &st =
287 static_cast<ELFSectionBitsTy const &>(*sec);
288 my_addr = const_cast<unsigned char *>(&st[0] + (off_t)getValue());
289 }
290 break;
291
292 case SHN_ABS:
293 case SHN_COMMON:
294 case SHN_XINDEX:
295 rsl_assert(0 && "STT_SECTION with special st_shndx.");
296 break;
297 case SHN_UNDEF:
298 return 0;
299 }
300 break;
301 return 0;
302
303 case STT_COMMON:
304 case STT_FILE:
305 case STT_TLS:
306 case STT_LOOS:
307 case STT_HIOS:
308 case STT_LOPROC:
309 case STT_HIPROC:
310 rsl_assert(0 && "Not implement.");
311 return 0;
312 }
313 return my_addr;
314 }
315
316 #endif // ELF_SYMBOL_HXX
317