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_H
18#define ELF_SYMBOL_H
19
20#include "ELFTypes.h"
21#include "ELF.h"
22
23#include <string>
24#include <algorithm>
25
26#include <stdint.h>
27#include <stdlib.h>
28
29class ELFSymbolHelperMixin {
30protected:
31  static char const *getTypeStr(uint8_t);
32  static char const *getBindingAttributeStr(uint8_t);
33  static char const *getVisibilityStr(uint8_t);
34};
35
36template <unsigned Bitwidth>
37class ELFSymbol_CRTP : private ELFSymbolHelperMixin {
38public:
39  ELF_TYPE_INTRO_TO_TEMPLATE_SCOPE(Bitwidth);
40
41protected:
42  ELFObject<Bitwidth> const *owner;
43
44  size_t index;
45
46  word_t st_name;
47  byte_t st_info;
48  byte_t st_other;
49  half_t st_shndx;
50  addr_t st_value;
51  symsize_t st_size;
52
53  mutable void *my_addr;
54
55protected:
56  ELFSymbol_CRTP() { my_addr = 0; }
57
58  ~ELFSymbol_CRTP() {
59#if 0
60    if (my_addr != 0 &&
61        getType() == STT_OBJECT &&
62        getSectionIndex() == SHN_COMMON) {
63      std::free(my_addr);
64    }
65#endif
66  }
67
68public:
69  size_t getIndex() const {
70    return index;
71  }
72
73  word_t getNameIndex() const {
74    return st_name;
75  }
76
77  char const *getName() const;
78
79// I don't want to include elf.h in .h file, so define those macro by ourself.
80#define ELF_ST_BIND(i)   ((i)>>4)
81#define ELF_ST_TYPE(i)   ((i)&0xf)
82#define ELF_ST_INFO(b,t) (((b)<<4)+((t)&0xf))
83  byte_t getType() const {
84    return ELF_ST_TYPE(st_info);
85  }
86
87  byte_t getBindingAttribute() const {
88    return ELF_ST_BIND(st_info);
89  }
90#undef ELF_ST_BIND
91#undef ELF_ST_TYPE
92#undef ELF_ST_INFO
93
94#define ELF_ST_VISIBILITY(o) ((o)&0x3)
95  byte_t getVisibility() const {
96    return ELF_ST_VISIBILITY(st_other);
97  }
98#undef ELF_ST_VISIBILITY
99
100  half_t getSectionIndex() const {
101    return st_shndx;
102  }
103
104  addr_t getValue() const {
105    return st_value;
106  }
107
108  symsize_t getSize() const {
109    return st_size;
110  }
111
112  void *getAddress(int machine, bool autoAlloc = true) const;
113
114  void setAddress(void *addr) {
115    my_addr = addr;
116  }
117
118  bool isValid() const {
119    // FIXME: Should check the correctness of the section header.
120    return true;
121  }
122
123  bool isConcreteFunc() const {
124    return getType() == STT_FUNC;
125  }
126
127  bool isExternFunc() const {
128    return getType() == STT_NOTYPE;
129  }
130
131  template <typename Archiver>
132  static ELFSymbolTy *
133  read(Archiver &AR, ELFObject<Bitwidth> const *owner, size_t index = 0);
134
135  void print(bool shouldPrintHeader = false) const;
136
137private:
138  ELFSymbolTy *concrete() {
139    return static_cast<ELFSymbolTy *>(this);
140  }
141
142  ELFSymbolTy const *concrete() const {
143    return static_cast<ELFSymbolTy const *>(this);
144  }
145};
146
147template <>
148class ELFSymbol<32> : public ELFSymbol_CRTP<32> {
149  friend class ELFSymbol_CRTP<32>;
150
151private:
152  ELFSymbol() {
153  }
154
155  template <typename Archiver>
156  bool serialize(Archiver &AR) {
157    AR.prologue(TypeTraits<ELFSymbol>::size);
158
159    AR & st_name;
160    AR & st_value;
161    AR & st_size;
162    AR & st_info;
163    AR & st_other;
164    AR & st_shndx;
165
166    AR.epilogue(TypeTraits<ELFSymbol>::size);
167    return AR;
168  }
169};
170
171template <>
172class ELFSymbol<64> : public ELFSymbol_CRTP<64> {
173  friend class ELFSymbol_CRTP<64>;
174
175private:
176  ELFSymbol() {
177  }
178
179  template <typename Archiver>
180  bool serialize(Archiver &AR) {
181    AR.prologue(TypeTraits<ELFSymbol>::size);
182
183    AR & st_name;
184    AR & st_info;
185    AR & st_other;
186    AR & st_shndx;
187    AR & st_value;
188    AR & st_size;
189
190    AR.epilogue(TypeTraits<ELFSymbol>::size);
191    return AR;
192  }
193};
194
195#include "impl/ELFSymbol.hxx"
196
197#endif // ELF_SYMBOL_H
198