• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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