/*
* 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_RELOC_H
#define ELF_RELOC_H
#include "ELFTypes.h"
#include "utils/rsl_assert.h"
#include <llvm/ADT/OwningPtr.h>
#include <string>
#include <stdint.h>
template <unsigned Bitwidth>
class ELFReloc_CRTP {
public:
ELF_TYPE_INTRO_TO_TEMPLATE_SCOPE(Bitwidth);
protected:
size_t index;
addr_t r_offset;
relinfo_t r_info;
addend_t r_addend;
protected:
ELFReloc_CRTP() : index(0), r_offset(0), r_addend(0) { }
~ELFReloc_CRTP() { }
public:
size_t getIndex() const {
return index;
}
addr_t getOffset() const {
return r_offset;
}
addend_t getAddend() const {
return r_addend;
}
bool isValid() const {
// FIXME: Should check the correctness of the relocation entite.
return true;
}
template <typename Archiver>
static ELFRelocTy *readRel(Archiver &AR, size_t index);
template <typename Archiver>
static ELFRelocTy *readRela(Archiver &AR, size_t index);
void print(bool shouldPrintHeader = false) const;
private:
ELFRelocTy *concrete() {
return static_cast<ELFRelocTy *>(this);
}
ELFRelocTy const *concrete() const {
return static_cast<ELFRelocTy const *>(this);
}
template <typename Archiver>
bool serializeRel(Archiver &AR) {
rsl_assert(r_addend == 0 && "r_addend should be zero before serialization.");
AR.prologue(TypeTraits<ELFRelocRelTy>::size);
AR & r_offset;
AR & r_info;
AR.epilogue(TypeTraits<ELFRelocRelTy>::size);
return AR;
}
template <typename Archiver>
bool serializeRela(Archiver &AR) {
AR.prologue(TypeTraits<ELFRelocRelaTy>::size);
AR & r_offset;
AR & r_info;
AR & r_addend;
AR.epilogue(TypeTraits<ELFRelocRelaTy>::size);
return AR;
}
};
template <>
class ELFReloc<32> : public ELFReloc_CRTP<32> {
friend class ELFReloc_CRTP<32>;
private:
ELFReloc() {
}
public:
word_t getSymTabIndex() const {
#define ELF32_R_SYM(i) ((i)>>8)
return ELF32_R_SYM(this->r_info);
#undef ELF32_R_SYM
}
word_t getType() const {
#define ELF32_R_TYPE(i) ((unsigned char)(i))
return ELF32_R_TYPE(this->r_info);
#undef ELF32_R_TYPE
}
};
template <>
class ELFReloc<64> : public ELFReloc_CRTP<64> {
friend class ELFReloc_CRTP<64>;
private:
ELFReloc() {
}
public:
xword_t getSymTabIndex() const {
#define ELF64_R_SYM(i) ((i)>>32)
return ELF64_R_SYM(this->r_info);
#undef ELF64_R_SYM
}
xword_t getType() const {
#define ELF64_R_TYPE(i) ((i)&0xffffffffL)
return ELF64_R_TYPE(this->r_info);
#undef ELF64_R_TYPE
}
};
#include "impl/ELFReloc.hxx"
#endif // ELF_RELOC_H