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
32template <unsigned Bitwidth>
33inline 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
42template <unsigned Bitwidth>
43template <typename Archiver>
44inline ELFSymbol<Bitwidth> *
45ELFSymbol_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
75template <unsigned Bitwidth>
76inline 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
121template <unsigned Bitwidth>
122void *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