/*
* 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