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 
29 class ELFSymbolHelperMixin {
30 protected:
31   static char const *getTypeStr(uint8_t);
32   static char const *getBindingAttributeStr(uint8_t);
33   static char const *getVisibilityStr(uint8_t);
34 };
35 
36 template <unsigned Bitwidth>
37 class ELFSymbol_CRTP : private ELFSymbolHelperMixin {
38 public:
39   ELF_TYPE_INTRO_TO_TEMPLATE_SCOPE(Bitwidth);
40 
41 protected:
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 
55 protected:
ELFSymbol_CRTP()56   ELFSymbol_CRTP() { my_addr = 0; }
57 
~ELFSymbol_CRTP()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 
68 public:
getIndex()69   size_t getIndex() const {
70     return index;
71   }
72 
getNameIndex()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))
getType()83   byte_t getType() const {
84     return ELF_ST_TYPE(st_info);
85   }
86 
getBindingAttribute()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)
getVisibility()95   byte_t getVisibility() const {
96     return ELF_ST_VISIBILITY(st_other);
97   }
98 #undef ELF_ST_VISIBILITY
99 
getSectionIndex()100   half_t getSectionIndex() const {
101     return st_shndx;
102   }
103 
getValue()104   addr_t getValue() const {
105     return st_value;
106   }
107 
getSize()108   symsize_t getSize() const {
109     return st_size;
110   }
111 
112   void *getAddress(int machine, bool autoAlloc = true) const;
113 
setAddress(void * addr)114   void setAddress(void *addr) {
115     my_addr = addr;
116   }
117 
isValid()118   bool isValid() const {
119     // FIXME: Should check the correctness of the section header.
120     return true;
121   }
122 
isConcreteFunc()123   bool isConcreteFunc() const {
124     return getType() == STT_FUNC;
125   }
126 
isExternFunc()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 
137 private:
concrete()138   ELFSymbolTy *concrete() {
139     return static_cast<ELFSymbolTy *>(this);
140   }
141 
concrete()142   ELFSymbolTy const *concrete() const {
143     return static_cast<ELFSymbolTy const *>(this);
144   }
145 };
146 
147 template <>
148 class ELFSymbol<32> : public ELFSymbol_CRTP<32> {
149   friend class ELFSymbol_CRTP<32>;
150 
151 private:
ELFSymbol()152   ELFSymbol() {
153   }
154 
155   template <typename Archiver>
serialize(Archiver & AR)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 
171 template <>
172 class ELFSymbol<64> : public ELFSymbol_CRTP<64> {
173   friend class ELFSymbol_CRTP<64>;
174 
175 private:
ELFSymbol()176   ELFSymbol() {
177   }
178 
179   template <typename Archiver>
serialize(Archiver & AR)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