/* * Copyright 2011, The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef ELF_SYMBOL_H #define ELF_SYMBOL_H #include "ELFTypes.h" #include "ELF.h" #include <llvm/ADT/OwningPtr.h> #include <string> #include <algorithm> #include <stdint.h> #include <stdlib.h> class ELFSymbolHelperMixin { protected: static char const *getTypeStr(uint8_t); static char const *getBindingAttributeStr(uint8_t); static char const *getVisibilityStr(uint8_t); }; template <unsigned Bitwidth> class ELFSymbol_CRTP : private ELFSymbolHelperMixin { public: ELF_TYPE_INTRO_TO_TEMPLATE_SCOPE(Bitwidth); protected: ELFObject<Bitwidth> const *owner; size_t index; word_t st_name; byte_t st_info; byte_t st_other; half_t st_shndx; addr_t st_value; symsize_t st_size; mutable void *my_addr; protected: ELFSymbol_CRTP() { my_addr = 0; } ~ELFSymbol_CRTP() { #if 0 if (my_addr != 0 && getType() == STT_OBJECT && getSectionIndex() == SHN_COMMON) { std::free(my_addr); } #endif } public: size_t getIndex() const { return index; } word_t getNameIndex() const { return st_name; } char const *getName() const; // I don't want to include elf.h in .h file, so define those macro by ourself. #define ELF_ST_BIND(i) ((i)>>4) #define ELF_ST_TYPE(i) ((i)&0xf) #define ELF_ST_INFO(b,t) (((b)<<4)+((t)&0xf)) byte_t getType() const { return ELF_ST_TYPE(st_info); } byte_t getBindingAttribute() const { return ELF_ST_BIND(st_info); } #undef ELF_ST_BIND #undef ELF_ST_TYPE #undef ELF_ST_INFO #define ELF_ST_VISIBILITY(o) ((o)&0x3) byte_t getVisibility() const { return ELF_ST_VISIBILITY(st_other); } #undef ELF_ST_VISIBILITY half_t getSectionIndex() const { return st_shndx; } addr_t getValue() const { return st_value; } symsize_t getSize() const { return st_size; } void *getAddress(int machine, bool autoAlloc = true) const; void setAddress(void *addr) { my_addr = addr; } bool isValid() const { // FIXME: Should check the correctness of the section header. return true; } bool isConcreteFunc() const { return getType() == STT_FUNC; } bool isExternFunc() const { return getType() == STT_NOTYPE; } template <typename Archiver> static ELFSymbolTy * read(Archiver &AR, ELFObject<Bitwidth> const *owner, size_t index = 0); void print(bool shouldPrintHeader = false) const; private: ELFSymbolTy *concrete() { return static_cast<ELFSymbolTy *>(this); } ELFSymbolTy const *concrete() const { return static_cast<ELFSymbolTy const *>(this); } }; template <> class ELFSymbol<32> : public ELFSymbol_CRTP<32> { friend class ELFSymbol_CRTP<32>; private: ELFSymbol() { } template <typename Archiver> bool serialize(Archiver &AR) { AR.prologue(TypeTraits<ELFSymbol>::size); AR & st_name; AR & st_value; AR & st_size; AR & st_info; AR & st_other; AR & st_shndx; AR.epilogue(TypeTraits<ELFSymbol>::size); return AR; } }; template <> class ELFSymbol<64> : public ELFSymbol_CRTP<64> { friend class ELFSymbol_CRTP<64>; private: ELFSymbol() { } template <typename Archiver> bool serialize(Archiver &AR) { AR.prologue(TypeTraits<ELFSymbol>::size); AR & st_name; AR & st_info; AR & st_other; AR & st_shndx; AR & st_value; AR & st_size; AR.epilogue(TypeTraits<ELFSymbol>::size); return AR; } }; #include "impl/ELFSymbol.hxx" #endif // ELF_SYMBOL_H